科學家在觀測一棵大樹,這棵樹在不斷地生長,科學家給這棵樹的每個節點編了號。開始的時候,這棵樹很小只有4個節點,一號點為根,其他三個節點掛在上面。
在接下來的m次觀察中,科學家每次都能看見這棵樹從葉子處長出新的兩個節點來。如果當前這棵樹有n個節點,那麼這棵樹的新的兩個節點的編號分別為n+1,n+2。科學家記錄下了這棵樹生長的過程,需要你幫著計算這棵樹實時的直徑。樹的直徑就是這棵樹最遠的兩個節點的距離。
第一行乙個整數m,代表觀察的次數。
接下來m行,每行乙個整數x,代表這棵樹的編號為x的節點下面又長了兩個葉子節點。保證每次生長的節點都是葉子節點。
m行,每次生長後這棵樹的直徑。
5 2
3 4 8 5
3 4
4 5
6對於10%的資料,n<=10
對於40%的資料,n<=1000
對於100%的資料,n<=100000。
首先要發現乙個性質,新直徑的兩端必定在有乙個端點在舊直徑上。
之後就可以先離線把所有點都增加好,建一棵樹,記錄一下每一輪新增加的點是哪兩個。
然後倍增一下求lca再算兩點路徑就可以了。
type
new=record
x,y:longint;
end;
var n,i,j,l1,r1,l,r,s,tot,x,cnt,s1,t:longint;
h,fa,next,head,b:array [0..250000] of longint;
anc:array [0..200500,0..18] of longint;
a:array [0..100050] of
new;
procedure
add(x,y:longint);
begin
inc(tot);
next[tot]:=head[x];
head[x]:=tot;
b[tot]:=y;
end;
procedure
dfs(x:longint);
var i,j:longint;
begin
anc[x,0]:=fa[x];
for i:=1
to18
do anc[x,i]:=anc[anc[x,i-1]][i-1];
i:=head[x];
while i<>0
dobegin
j:=b[i];
if j<>fa[x] then
begin
fa[j]:=x;
h[j]:=h[x]+1;
dfs(j);
end;
i:=next[i];
end;
end;
function
lca(x,y:longint):longint;
var i:longint;
begin
if h[x]then
begin
i:=x; x:=y; y:=i;
end;
for i:=18
downto0do
if h[anc[x,i]]>=h[y] then x:=anc[x,i];
if x=y then
exit(x);
for i:=18
downto0do
if (anc[x,i]<>anc[y,i]) then
begin
x:=anc[x,i];
y:=anc[y,i];
end;
exit(anc[x,0]);
end;
begin
readln(n);
add(1,2);
add(1,3);
add(1,4);
cnt:=4;
for i:=1
to n do
begin
read(x);
inc(cnt);
a[i].x:=cnt;
add(x,cnt);
inc(cnt);
a[i].y:=cnt;
add(x,cnt);
end;
fa[1]:=1;
h[1]:=1;
dfs(1);
l:=2; r:=4; s:=2;
for i:=1
to n do
begin
t:=lca(l,a[i].x);
s1:=h[l]+h[a[i].x]-2*h[t];
if s1>s then
begin
l1:=l; r1:=a[i].x;
s:=s1;
end;
t:=lca(r,a[i].x);
s1:=h[r]+h[a[i].x]-2*h[t];
if s1>s then
begin
l1:=a[i].x; r1:=r; s:=s1;
end;
t:=lca(l,a[i].y);
s1:=h[l]+h[a[i].y]-2*h[t];
if s1>s then
begin
l1:=l; r1:=a[i].y; s:=s1;
end;
t:=lca(r,a[i].y);
s1:=h[r]+h[a[i].y]-2*h[t];
if s1>s then
begin
l1:=r; r1:=a[i].y; s:=s1;
end;
writeln(s);
l:=l1; r:=r1;
end;
end.
Jzoj3555 樹的直徑
科學家在觀測一棵大樹,這棵樹在不斷地生長,科學家給這棵樹的每個節點編了號。開始的時候,這棵樹很小只有4個節點,一號點為根,其他三個節點掛在上面。在接下來的m次觀察中,科學家每次都能看見這棵樹從葉子處長出新的兩個節點來。如果當前這棵樹有n個節點,那麼這棵樹的新的兩個節點的編號分別為n 1,n 2。科學...
SDOI2013 直徑(樹的直徑)
小q最近學習了一些圖論知識。根據課本,有如下定義。樹 無迴路且連通的無向圖,每條邊都有正整數的權值來表示其長度。如果一棵樹有n個節點,可以證明其有且僅有n 1 條邊。路徑 一棵樹上,任意兩個節點之間最多有一條簡單路徑。我們用 dis a,b 表示點a和點b的路徑上各邊長度之和。稱dis a,b 為a...
JZOJ5465 道路重建 邊雙縮點 樹的直徑
lueluelue 這鬼題卡了我10發提交,之前做過一道類似的題目 題解p2860 usaco冗雜路徑 縮點 橋 危險的邊就是橋邊,tarjan求出邊雙后縮點整個圖變成樹,樹邊都是危險的邊,我們需要加一條邊構成乙個新的ecc使危險的邊最小 於是一開始naiive的以為求出所有葉子節點判一判就好了,於...