简单的LCA.
有一个结论,每个party中最远的点对中,必有一个点是该party中深度最大的点.
然后记low[i]为第i个party的最深点,对每一个点查询dist(i,low[belong[i]]).
belong就是第i个点属于哪个party.
对于树上两点,dist(u,v)=depth(u)+depth(v)-2*depth(lca(u,v)).
一开时用RMQ的LCA死活过不去.无奈,只好去学了tarjan的LCA.
code:
/************************************************************** Problem: 1776 User: exponent Language: Pascal Result: Accepted Time:1940 ms Memory:15628 kb ****************************************************************/ {$M 10000000} type edge=record v,n:longint; end; const maxn=200001; maxk=100000; var e:array[0..maxn] of edge; g:array[0..maxn*2] of edge; h,hx,q,d,b,f,dep,anc:array[0..maxn] of longint; vis:array[0..maxn] of boolean; low,ans:array[0..maxk] of longint; n,i,k,fi,cx,cnt,root:longint; procedure add(u,v:longint); begin inc(cnt); e[cnt].v:=v; e[cnt].n:=h[u]; h[u]:=cnt; end; procedure addx(u,v:longint); begin inc(cx); g[cx].v:=v; g[cx].n:=hx[u]; hx[u]:=cx; end; procedure bfs(u:longint); var v,p,head,tail:longint; begin head:=0; tail:=1; q[1]:=u; d[1]:=1; while head<tail do begin inc(head); u:=q[head]; low[b[u]]:=u; dep[u]:=d[head]; p:=h[u]; while p<>0 do begin v:=e[p].v; inc(tail); q[tail]:=v; d[tail]:=d[head]+1; p:=e[p].n; end; end; end; function getf(x:longint):longint; begin if f[x]<>x then f[x]:=getf(f[x]); exit(f[x]); end; procedure union(u,v:longint); var fu,fv:longint; begin fu:=getf(u); fv:=getf(v); if fu<>fv then f[fu]:=fv; end; function max(a,b:longint):longint; begin if a>b then exit(a); exit(b); end; procedure LCA(u:longint); var v,p,fx:longint; begin anc[u]:=u; p:=h[u]; while p<>0 do begin v:=e[p].v; LCA(v); union(u,v); anc[getf(u)]:=u; p:=e[p].n; end; vis[u]:=true; p:=hx[u]; while p<>0 do begin v:=g[p].v; if vis[v] then begin fx:=anc[getf(v)]; ans[b[u]]:=max(ans[b[u]],dep[u]+dep[v]-dep[fx]*2); end; p:=g[p].n; end; end; begin readln(n,k); for i:=1 to n do begin readln(b[i],fi); add(fi,i); if fi=0 then root:=i; end; Bfs(root); for i:=1 to n do begin f[i]:=i; addx(i,low[b[i]]); addx(low[b[i]],i); end; LCA(root); for i:=1 to k do writeln(ans[i]); end.