您的位置:首页 > 其它

[BZOJ3611] [Heoi2014]大工程

2016-03-04 18:47 399 查看

传送门

http://www.lydsy.com/JudgeOnline/problem.php?id=3611

题目大意

给定一些树上的关键点询问

1.两两之间的路径和

2.两两之间的最长路径

3.两两之间的最短路径

题解

虚树+树形DP

第一个问题

f[i]+=f[son[i]]+size[son[i]]∗(cnt−size[son[i]])∗dis(i,son[i])f[i]+=f[son[i]]+size[son[i]]*(cnt-size[son[i]])*dis(i,son[i])

cntcnt为关键点总数,size[i]size[i]为以ii为根的子树内关键点个数

第二,三个问题

minans=min(minans,g[i]+g[son[i]]+dis(i,son[i]))minans=min(minans,g[i]+g[son[i]]+dis(i,son[i]))

g[i]g[i]为以ii为根的子树中到ii的最小长度

maxmax同理

注意初值

const
maxn=1000050;
maxint=1000000000;
var
w:array[0..3*maxn,1..2]of longint;
t,x,dep,pos,g,h,cle:array[0..maxn]of longint; {g-->min;h-->max}
size,f:array[0..maxn]of int64;
st:array[0..maxn,0..20]of longint;
i,j,k:longint;
n,m,len,a,b,top,cnt,ans1,ans2,tt:Longint; {ans1-->min;ans2-->max}
function min(a,b:longint):longint;
begin if a>b then exit(b) else exit(a); end;

function max(a,b:longint):longint;
begin if a<b then exit(b) else exit(a); end;

procedure init(a,b:longint);
begin
w[len,1]:=b;
if w[a,2]=0 then w[a,2]:=len else w[w[a,1],2]:=len;
w[a,1]:=len; inc(len);
end;

procedure sort(l,r:longint);
var i,j,a,b:longint;
begin
i:=l; j:=r; a:=pos[x[(l+r)div 2]];
repeat
while (pos[x[i]]<a) do inc(i);
while (a<pos[x[j]]) do dec(j);
if not (i>j) then
begin
b:=x[i]; x[i]:=x[j]; x[j]:=b;
inc(i); dec(j);
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end;

procedure dfs(a,fa:longint);
var tt:longint;
begin
tt:=w[a,2]; inc(len); pos[a]:=len; st[a,0]:=fa;
while tt<>0 do
begin
if (w[tt,1]<>fa) then
begin
dep[w[tt,1]]:=dep[a]+1;
dfs(w[tt,1],a);
end;
tt:=w[tt,2];
end;
end;

function lca(a,b:longint):longint;
var i:longint;
begin
if dep[a]<dep[b] then begin i:=a; a:=b; b:=i; end;
for i:=20 downto 0 do
if dep[st[a,i]]>=dep[b] then a:=st[a,i];
if a=b then exit(a);
for i:=20 downto 0 do
if st[a,i]<>st[b,i] then begin a:=st[a,i]; b:=st[b,i]; end;
exit(st[a,0]);
end;

procedure dp(a,fa:longint); {g-->min;h-->max} {ans1-->min;ans2-->max}
begin
f[fa]:=f[fa]+f[a]+size[a]*(cnt-size[a])*(dep[a]-dep[fa]);
size[fa]:=size[fa]+size[a];
ans1:=min(ans1,g[fa]+g[a]+dep[a]-dep[fa]);
ans2:=max(ans2,h[fa]+h[a]+dep[a]-dep[fa]);
g[fa]:=min(g[fa],g[a]+dep[a]-dep[fa]);
h[fa]:=max(h[fa],h[a]+dep[a]-dep[fa]);
end;

begin
readln(n); len:=n+1;
for i:=1 to n-1 do begin readln(a,b); init(a,b); init(b,a); end;
init(0,1); init(1,0);
len:=0; dep[0]:=1; st[0,0]:=0; dfs(0,0);
for j:=1 to 20 do
for i:=1 to n do
st[i,j]:=st[st[i,j-1],j-1];
for i:=0 to n do begin g[i]:=maxint; h[i]:=-maxint; end;
readln(m);
for i:=1 to m do
begin
readln(cnt);
for j:=1 to cnt do begin read(x[j]); size[x[j]]:=1; cle[j]:=x[j]; g[x[j]]:=0; h[x[j]]:=0; end;
sort(1,cnt);
top:=1; t[1]:=0; cle[0]:=cnt+1; cle[cnt+1]:=0; ans1:=maxint; ans2:=-maxint;
for j:=1 to cnt do
begin
tt:=lca(t[top],x[j]);
while (dep[tt]<dep[t[top]]) do
begin
if (dep[t[top-1]]<=dep[tt]) then
begin
dp(t[top],tt); {dp(t[top]-->tt)} dec(top);
if (t[top]<>tt) then begin inc(top); t[top]:=tt; inc(cle[0]); cle[cle[0]]:=tt; end;
break;
end;
dp(t[top],t[top-1]); {dp(t[top]-->t[top-1])} dec(top);
end;
inc(top); t[top]:=x[j];
end;
while (top>1) do
begin
dp(t[top],t[top-1]); {dp(t[top]-->t[top-1])} dec(top);
end;
writeln(f[0],' ',ans1,' ',ans2);
for j:=1 to cle[0] do
begin
size[cle[j]]:=0;
f[cle[j]]:=0;
g[cle[j]]:=maxint;
h[cle[j]]:=-maxint;
end;
end;
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: