jzoj3555 樹的直徑

2021-08-11 20:26:18 字數 2850 閱讀 5379

科學家在觀測一棵大樹,這棵樹在不斷地生長,科學家給這棵樹的每個節點編了號。開始的時候,這棵樹很小只有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的以為求出所有葉子節點判一判就好了,於...