码迷,mamicode.com
首页 > 其他好文 > 详细

codeforces 980E The Number Games

时间:2018-07-28 12:14:27      阅读:160      评论:0      收藏:0      [点我收藏+]

标签:class   多选   dep   col   最大   roo   games   size   force   

题目大意:

题目大意 : 有一棵点数为 n 的数,第 ii 个点的点权是 2i 你需要删掉 k 个点,使得删掉这些点后树依然联通,且剩下的点权之和最大,并输出方案

n,k≤1000000

解题思路 :

该问题可以转化为选取 n?k个点,使得选取的点联通且权值和最大

根据点权是 2i,有选取编号为 x 的点比选取 i=[1,x)之间的所有点还要优(手推一下就知道啦)

首先 n 一定要保留,于是可以将 n设置为 root 把无根树变成有根树来简化问题

接下来不妨贪心的从大到小枚举点,对于当前的点,判断是否已经被标记,如果没有被标记,那么就找到离当前点最远的没有被标记的祖先,

如果要标记这个点,那么总共增加的点就是从当前点到离当前点最远的没有被标记的祖先的路径上的所有点的数量,也可以解释为当前点到已经保留的点所构成的树的路径上的点。

所以对于一个点 x 只需要倍增找到其到 root 路径上最深的未被选取的点 y

那么路径上没有被选取的点的个数就是 dep[x]-dep[y]+1如果可以选取就dfs枚举这些点并标记为取。

因为每个点只会被最多选取一次,总复杂度是 O(nlogn)

var
a,next,head,dep:array[0..2000005]of longint;
f:array[0..1000005,0..24]of longint;
vis:array[0..2000005]of boolean;
i,n,m,k,e,root,u,v,fi,j,x,y:longint;
procedure add(x,y:longint);
 begin
  inc(e);a[e]:=y;next[e]:=head[x];head[x]:=e;
 end;
 procedure dfs(x:longint);//预处理深度
  var i,v:longint;
   begin
   i:=head[x];
   while i>0 do
    begin
     v:=a[i];
      if dep[v]=0 then
        begin
         dep[v]:=dep[x]+1;
         f[v,0]:=x;
         dfs(v);
        end;
     i:=next[i];
    end;
  end;
  function get(x:longint):longint;//找最远的未被访问的点,倍增
   var i:longint;
   begin
     for i:=22 downto  0 do
     begin
      if (not(vis[f[x,i]]))and(f[x,i]<>0)then  x:=f[x,i];
     end;
     exit(x);
   end;
   procedure redfs(u,x:longint);//向上标记点
    var i:longint;
     begin
      vis[u]:=true;
      if u=x then exit;
      redfs(f[u,0],x);
     end;
begin
 readln(n,k);k:=n-k-1;//节点n占掉一个位子
 for i:=1 to n-1 do
  begin
   readln(x,y);
   add(x,y);
   add(y,x);
  end;
 root:=n;
 f[root,0]:=root;//预处理
 dep[root]:=1;
 dfs(root);

 for i:=1 to 22 do
  for j:=1 to n do
    begin
     f[j,i]:=f[f[j,i-1],i-1];//倍增初始化
    end;
    vis[n]:=true;
  for i:=n-1 downto 1 do
   if not vis[i]  then
    begin
      u:=i;fi:=get(u);
      if dep[u]-dep[fi]+1<=k then
        begin
         k:=k-(dep[u]-dep[fi]+1);
        // writeln(k);
         redfs(u,fi);
        end;
    end;
    for i:=1 to n do if not vis[i] then write(i, );
end.

 

codeforces 980E The Number Games

标签:class   多选   dep   col   最大   roo   games   size   force   

原文地址:https://www.cnblogs.com/brilliant107/p/9380537.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!