【BZOJ3611】大工程(虚树,DFS序,树形DP)

题意:有一棵树,树有边权,有若干次询问,给出一些点,求:

1.这些点互相之间的距离之和

2.点对距离中的最大和最小值

n<=1000000 

q<=50000并且保证所有k之和<=2*n 
 
思路:感谢Gold_7
建立虚树,在上面树形DP即可
最大值和最小值用了一种精妙的写法来保证是最值+次值
终于会写类似点对距离和的树形DP了
  1 var head,vet,next,len,
  2     head1,vet1,next1,len1,
  3     h,stk,b,dep,dfn,flag,c:array[0..2100000]of longint;
  4     dp:array[1..1000000,1..2]of longint;
  5     size,g:array[1..1000000]of int64;
  6     f:array[1..1000000,0..21]of longint;
  7     n,i,tot,que,ans1,ans2,time,x,y:longint;
  8     ans:int64;
  9 
 10 procedure swap(var x,y:longint);
 11 var t:longint;
 12 begin
 13  t:=x; x:=y; y:=t;
 14 end;
 15 
 16 function min(x,y:int64):int64;
 17 begin
 18  if x<y then exit(x);
 19  exit(y);
 20 end;
 21 
 22 function max(x,y:int64):int64;
 23 begin
 24  if x>y then exit(x);
 25  exit(y);
 26 end;
 27 
 28 procedure add(a,b,c:longint);
 29 begin
 30  inc(tot);
 31  next[tot]:=head[a];
 32  vet[tot]:=b;
 33  len[tot]:=c;
 34  head[a]:=tot;
 35 end;
 36 
 37 procedure qsort(l,r:longint);
 38 var i,j,mid:longint;
 39 begin
 40  i:=l; j:=r; mid:=b[(l+r)>>1];
 41  repeat
 42   while mid>b[i] do inc(i);
 43   while mid<b[j] do dec(j);
 44   if i<=j then
 45   begin
 46    swap(h[i],h[j]);
 47    swap(b[i],b[j]);
 48    inc(i); dec(j);
 49   end;
 50  until i>j;
 51  if l<j then qsort(l,j);
 52  if i<r then qsort(i,r);
 53 end;
 54 
 55 function lca(x,y:longint):longint;
 56 var i,d:longint;
 57 begin
 58  if dep[x]<dep[y] then swap(x,y);
 59  d:=dep[x]-dep[y];
 60  for i:=0 to 21 do
 61   if d and (1<<i)>0 then x:=f[x,i];
 62  for i:=21 downto 0 do
 63   if f[x,i]<>f[y,i] then
 64   begin
 65    x:=f[x,i]; y:=f[y,i];
 66   end;
 67  if x=y then exit(x);
 68  exit(f[x,0]);
 69 end;
 70 
 71 procedure dfs(u:longint);
 72 var e,v,i:longint;
 73 begin
 74  for i:=1 to 21 do
 75  begin
 76   if dep[u]<(1<<i) then break;
 77   f[u,i]:=f[f[u,i-1],i-1];
 78  end;
 79  inc(time); dfn[u]:=time;
 80  flag[u]:=1;
 81  e:=head[u];
 82  while e<>0 do
 83  begin
 84   v:=vet[e];
 85   if flag[v]=0 then
 86   begin
 87    f[v,0]:=u;
 88    dep[v]:=dep[u]+1;
 89    dfs(v);
 90   end;
 91   e:=next[e];
 92  end;
 93 end;
 94 
 95 procedure add1(a,b:longint);
 96 begin
 97  if a=b then exit;
 98  inc(tot);
 99  next1[tot]:=head1[a];
100  vet1[tot]:=b;
101  len1[tot]:=abs(dep[a]-dep[b]);
102  head1[a]:=tot;
103 end;
104 
105 procedure dfs2(u:longint);
106 var e,v:longint;
107 begin
108  size[u]:=c[u];
109  g[u]:=0;
110  if c[u]=1 then begin dp[u,1]:=0; dp[u,2]:=0; end
111   else begin dp[u,1]:=-maxlongint div 3; dp[u,2]:=maxlongint div 3; end;
112  e:=head1[u];
113  while e<>0 do
114  begin
115   v:=vet1[e];
116   dfs2(v);
117   ans:=ans+size[v]*g[u]+size[u]*g[v]+size[u]*size[v]*len1[e];
118   size[u]:=size[u]+size[v];
119   g[u]:=g[u]+g[v]+size[v]*len1[e];
120   ans1:=max(ans1,dp[u,1]+dp[v,1]+len1[e]);
121   ans2:=min(ans2,dp[u,2]+dp[v,2]+len1[e]);
122   dp[u,1]:=max(dp[u,1],dp[v,1]+len1[e]);
123   dp[u,2]:=min(dp[u,2],dp[v,2]+len1[e]);
124   e:=next1[e];
125  end;
126  head1[u]:=0;
127 end;
128 
129 procedure solve;
130 var q,top,i,now,m,p:longint;
131 begin
132  tot:=0;
133  read(m);
134  for i:=1 to m do
135  begin
136   read(h[i]); b[i]:=dfn[h[i]];
137   c[h[i]]:=1;
138  end;
139  qsort(1,m);
140  //q:=1;
141  //for i:=2 to m do
142   //if lca(h[i],h[q])<>h[q] then begin inc(q); h[q]:=h[i]; end;
143  stk[1]:=1; top:=1;
144  for i:=1 to m do
145  begin
146   now:=h[i]; p:=lca(now,stk[top]);
147   while true do
148   begin
149    if dep[p]>=dep[stk[top-1]] then
150    begin
151     add1(p,stk[top]); dec(top);
152     if stk[top]<>p then begin inc(top); stk[top]:=p; end;
153     break;
154    end;
155    add1(stk[top-1],stk[top]); dec(top);
156   end;
157   if stk[top]<>now then begin inc(top); stk[top]:=now; end;
158  end;
159  for i:=top-1 downto 1 do add1(stk[i],stk[i+1]);
160  ans:=0; ans1:=-maxlongint div 3; ans2:=maxlongint div 3;
161  dfs2(1);
162  writeln(ans,' ',ans2,' ',ans1);
163  for i:=1 to m do c[h[i]]:=0;
164 end;
165 
166 
167 begin
168 
169  readln(n);
170  for i:=1 to n-1 do
171  begin
172   readln(x,y);
173   add(x,y,1);
174   add(y,x,1);
175  end;
176  dfs(1);
177  readln(que);
178  for i:=1 to que do solve;
179  
180 end.

 

%了XYZ(虚树发明者)论文后的新的建虚树方法,简明易懂:
1:加入所有原关键点并按DFS序排序
2:将排序后两两相邻点对的LCA加入后去重,并再次排序
3:将第二次排序后的点依次入栈,若栈顶元素y非插入元素x的祖先则退栈,直到栈顶元素为x的祖先为止,链接x,y
  1 var head,vet,next,len,
  2     head1,vet1,next1,len1,
  3     h,stk,b,dep,dfn,flag,c,d:array[0..2100000]of longint;
  4     dp:array[1..1000000,1..2]of longint;
  5     size,g:array[1..1000000]of int64;
  6     f:array[1..1000000,0..21]of longint;
  7     n,i,tot,que,ans1,ans2,time,x,y:longint;
  8     ans:int64;
  9 
 10 procedure swap(var x,y:longint);
 11 var t:longint;
 12 begin
 13  t:=x; x:=y; y:=t;
 14 end;
 15 
 16 function min(x,y:int64):int64;
 17 begin
 18  if x<y then exit(x);
 19  exit(y);
 20 end;
 21 
 22 function max(x,y:int64):int64;
 23 begin
 24  if x>y then exit(x);
 25  exit(y);
 26 end;
 27 
 28 procedure add(a,b,c:longint);
 29 begin
 30  inc(tot);
 31  next[tot]:=head[a];
 32  vet[tot]:=b;
 33  len[tot]:=c;
 34  head[a]:=tot;
 35 end;
 36 
 37 procedure qsort1(l,r:longint);
 38 var i,j,mid:longint;
 39 begin
 40  i:=l; j:=r; mid:=b[(l+r)>>1];
 41  repeat
 42   while mid>b[i] do inc(i);
 43   while mid<b[j] do dec(j);
 44   if i<=j then
 45   begin
 46    swap(h[i],h[j]);
 47    swap(b[i],b[j]);
 48    inc(i); dec(j);
 49   end;
 50  until i>j;
 51  if l<j then qsort1(l,j);
 52  if i<r then qsort1(i,r);
 53 end;
 54 
 55 procedure qsort2(l,r:longint);
 56 var i,j,mid:longint;
 57 begin
 58  i:=l; j:=r; mid:=b[(l+r)>>1];
 59  repeat
 60   while mid>b[i] do inc(i);
 61   while mid<b[j] do dec(j);
 62   if i<=j then
 63   begin
 64    swap(d[i],d[j]);
 65    swap(b[i],b[j]);
 66    inc(i); dec(j);
 67   end;
 68  until i>j;
 69  if l<j then qsort2(l,j);
 70  if i<r then qsort2(i,r);
 71 end;
 72 
 73 function lca(x,y:longint):longint;
 74 var i,d:longint;
 75 begin
 76  if dep[x]<dep[y] then swap(x,y);
 77  d:=dep[x]-dep[y];
 78  for i:=0 to 21 do
 79   if d and (1<<i)>0 then x:=f[x,i];
 80  for i:=21 downto 0 do
 81   if f[x,i]<>f[y,i] then
 82   begin
 83    x:=f[x,i]; y:=f[y,i];
 84   end;
 85  if x=y then exit(x);
 86  exit(f[x,0]);
 87 end;
 88 
 89 procedure dfs(u:longint);
 90 var e,v,i:longint;
 91 begin
 92  for i:=1 to 21 do
 93  begin
 94   if dep[u]<(1<<i) then break;
 95   f[u,i]:=f[f[u,i-1],i-1];
 96  end;
 97  inc(time); dfn[u]:=time;
 98  flag[u]:=1;
 99  e:=head[u];
100  while e<>0 do
101  begin
102   v:=vet[e];
103   if flag[v]=0 then
104   begin
105    f[v,0]:=u;
106    dep[v]:=dep[u]+1;
107    dfs(v);
108   end;
109   e:=next[e];
110  end;
111 end;
112 
113 procedure add1(a,b:longint);
114 begin
115  if a=b then exit;
116  inc(tot);
117  next1[tot]:=head1[a];
118  vet1[tot]:=b;
119  len1[tot]:=abs(dep[a]-dep[b]);
120  head1[a]:=tot;
121 end;
122 
123 procedure dfs2(u:longint);
124 var e,v:longint;
125 begin
126  size[u]:=c[u];
127  g[u]:=0;
128  if c[u]=1 then begin dp[u,1]:=0; dp[u,2]:=0; end
129   else begin dp[u,1]:=-maxlongint div 3; dp[u,2]:=maxlongint div 3; end;
130  e:=head1[u];
131  while e<>0 do
132  begin
133   v:=vet1[e];
134   dfs2(v);
135   ans:=ans+size[v]*g[u]+size[u]*g[v]+size[u]*size[v]*len1[e];
136   size[u]:=size[u]+size[v];
137   g[u]:=g[u]+g[v]+size[v]*len1[e];
138   ans1:=max(ans1,dp[u,1]+dp[v,1]+len1[e]);
139   ans2:=min(ans2,dp[u,2]+dp[v,2]+len1[e]);
140   dp[u,1]:=max(dp[u,1],dp[v,1]+len1[e]);
141   dp[u,2]:=min(dp[u,2],dp[v,2]+len1[e]);
142   e:=next1[e];
143  end;
144  head1[u]:=0;
145 end;
146 
147 procedure solve;
148 var q,top,i,now,m,p:longint;
149 begin
150  tot:=0;
151  read(m);
152  for i:=1 to m do
153  begin
154   read(h[i]); b[i]:=dfn[h[i]];
155   c[h[i]]:=1;
156  end;
157  qsort1(1,m);
158  q:=0;
159  for i:=1 to m do
160  begin
161   inc(q); d[q]:=h[i]; flag[h[i]]:=1;
162  end;
163  for i:=1 to m-1 do
164  begin
165   p:=lca(h[i],h[i+1]);
166   if flag[p]=0 then begin flag[p]:=1; inc(q); d[q]:=p; end;
167  end;
168  for i:=1 to q do b[i]:=dfn[d[i]];
169  qsort2(1,q);
170 
171  stk[1]:=d[1]; top:=1;
172  for i:=2 to q do
173  begin
174   x:=d[i];
175   while true do
176   begin
177    y:=stk[top];
178    if lca(x,y)<>y then dec(top)
179     else
180     begin
181      add1(y,x);
182      break;
183     end;
184   end;
185   inc(top); stk[top]:=x;
186  end;
187 
188 
189  ans:=0; ans1:=-maxlongint div 3; ans2:=maxlongint div 3;
190  dfs2(d[1]);
191  writeln(ans,' ',ans2,' ',ans1);
192  for i:=1 to m do c[h[i]]:=0;
193  for i:=1 to q do flag[d[i]]:=0;
194 end;
195 
196 
197 begin
198  assign(input,'bzoj3611.in'); reset(input);
199  assign(output,'bzoj3611.out'); rewrite(output);
200  readln(n);
201  for i:=1 to n-1 do
202  begin
203   readln(x,y);
204   add(x,y,1);
205   add(y,x,1);
206  end;
207  dfs(1);
208  readln(que);
209  fillchar(flag,sizeof(flag),0);
210  for i:=1 to que do solve;
211  close(input);
212  close(output);
213 end.

 

 

posted on 2016-12-16 16:59  myx12345  阅读(404)  评论(0编辑  收藏  举报

导航