题意:n个结点的树,m种颜色,求每种颜色中距离最远的两点的距离
易知,距离最远的两点中一定有一个点是该颜色深度最深的点,另一个枚举求lca更新即可
小机智:求出每种颜色深度最深的点后,枚举颜色再枚举结点更新该颜色的答案显然是会吃TLE的,所以我们枚举n个结点,判断每个节点对它所属于的颜色是否能更新,这样降下了复杂度
var
n,m,l,x,tt,root :longint;
i,j :longint;
vis :array[0..200010] of boolean;
a,d,last :array[0..200010] of longint;
ans,maxn :array[0..100010] of longint;
pre,other,len :array[0..200010] of longint;
jump :array[0..200010,0..20] of longint;
procedure swap(var a,b:longint);
var
c:longint;
begin
c:=a; a:=b; b:=c;
end;
procedure connect(x,y:longint);
begin
inc(l);
pre[l]:=last[x];
last[x]:=l;
other[l]:=y;
end;
procedure dfs(x:longint);
var
p,q:longint;
begin
q:=last[x];
while (q<>0) do
begin
p:=other[q];
if not vis[p] then
begin
vis[p]:=true;
d[p]:=d[x]+1;
jump[p,0]:=x;
dfs(p);
end;
q:=pre[q];
end;
end;
function lca(x,y:longint):longint;
var
ans:longint;
i,j:longint;
begin
ans:=0;
if d[x]>d[y] then swap(x,y);
for i:=0 to 20 do
if ((d[y]-d[x]) and (1<<i) <>0) then
begin
inc(ans,1<<i);
y:=jump[y,i];
end;
//
if x=y then exit(ans);
for i:=20 downto 0 do
if jump[x,i]<>jump[y,i] then
begin
inc(ans,1<<i);
inc(ans,1<<i);
x:=jump[x,i];
y:=jump[y,i];
end;
inc(ans,2);
exit(ans);
end;
begin
read(n,m);
for i:=1 to n do
begin
read(a[i],x);
if x=0 then root:=i else connect(x,i);
end;
vis[root]:=true; d[root]:=1; dfs(root);
for j:=1 to 20 do
for i:=1 to n do jump[i,j]:=jump[jump[i,j-1],j-1];
//
for i:=1 to n do
if d[i]>d[maxn[a[i]]] then maxn[a[i]]:=i;
for i:=1 to n do
begin
tt:=lca(i,maxn[a[i]]);
if tt>ans[a[i]] then ans[a[i]]:=tt;
end;
//
for i:=1 to m do writeln(ans[i]);
end.
——by Eirlys

本文探讨了在树形结构中使用特定算法解决颜色最远距离问题的方法。通过找到每种颜色深度最深的点,并利用LCA算法计算距离,有效解决了复杂度问题。
337

被折叠的 条评论
为什么被折叠?



