樹中兩點間的不重複經過的邊和點道路稱為兩點的路徑,路徑的長度(路徑上所經邊的長度和)稱為兩點的距離。圓的直徑是乙個圓的最長的一條弦,而樹的直徑是樹中兩點間最長的路徑。通常用乙個無序點對(x,y)表示一棵樹的直徑。
現在輸入乙個有n個結點的樹,結點編號為1到n,假設結點1為根。試求樹的直徑。
輸入格式
輸入包含n+1行,第一行為1個正整數n,表示樹的結點個數。
接下來n-1行,每行兩個整數x和y,表示結點x和y之間有一條邊,其中x是y的父親。
輸出格式
輸出只有乙個整數,為樹的直徑。
資料範圍n≤1
05n≤10^5
n≤10
5輸入樣例
6輸出樣例 在樹中任取乙個結點t5 1 6
1 4 5
6 3 9
2 6 8
6 1 7
tt,求到t
tt距離最遠的結點u
uu,接著求到u
uu距離最遠的結點v
vv,那麼結點u
uu和v
vv之間的路徑就是樹的一條直徑。
根據上述思想,只需證明第一次找到的結點u
uu一定是某條直徑的端點即可。
反證法:假設距離t
tt最遠的結點u
uu不是某條直徑的端點,並且存在某條直徑,其端點分別為x
xx、y
yy。那麼t
tt到u
uu之間的路徑和x
xx到y
yy 之間的路徑,根據有無公共結點,可分為相交和不相交兩種情況,如下圖所示:
不相交的情況
因為樹是連通的,所以從結點t
tt一定存在一條路徑能夠到達結點y
yy,如下圖所示:
由於u
uu是到t
tt距離最遠的點,所以①+②
≥①+⑤
+④①+②\ge①+⑤+④
①+②≥①+
⑤+④,那麼②≥⑤
+④②\ge⑤+④
②≥⑤+④,②+⑤
≥④②+⑤\ge④
②+⑤≥
④。我們假設xyxy
xy是樹的一條直徑,即③+④
③+④③+
④一定是樹中最長的路徑,而②+⑤
+③≥③
+④②+⑤+③\ge③+④
②+⑤+③≥
③+④,所以如結點u
uu不是某條直徑的端點,那麼樹中一定存在一條大於等於當前直徑的路徑,與假設矛盾。
相交的情況
由於u
uu是到t
tt距離最遠的點,所以①+②
≥①+④
①+②\ge①+④
①+②≥①+
④,即②≥④
②\ge④
②≥④,那麼③+②
≥③+④
③+②\ge③+④
③+②≥③+
④。我們假設xyxy
xy是樹的一條直徑,即③+④
③+④③+
④一定是樹中最長的路徑,如果結點u
uu不是某條直徑的端點,那麼樹中一定存在一條大於等於當前直徑的路徑,與假設矛盾。
證畢。使用鄰接表實現一棵無根樹,在樹中任取乙個結點t
:
通過dfs求出所有點i
到t
的距離dep[i]
打擂台,求出到t
距離最遠的結點u
使用相同的方法求出到u
距離最遠的結點v
dep[v]
就是樹的直徑
需要對所有節點遍歷一次,時間複雜度為o(n
)o(n)
o(n)
#include
#include
using
namespace std;
const
int n =
100010
, m = n *2;
int h[n]
, e[m]
, ne[m]
, idx;
int n, dep[n]
;//鄰接表,向鍊錶頭部插入新結點
void
add(
int a,
int b)
//求以u為根的子樹中所有結點到根結點的深度
intdfs
(int u,
int fa,
int depth)
}int
main()
//任選一點u作為根結點,求所有點到u的距離
int u =1;
dfs(u,0,
0);//求距離最遠的點u
for(
int i =
1; i <= n; i ++)}
//以u作為根結點,求所有點到u的距離
dfs(u,0,
0);//求距離最遠的點u
for(
int i =
1; i <= n; i ++)}
cout << dep[u]
<< endl;
return0;
}
#include
#include
using
namespace std;
const
int n =
100010
, m =
2* n;
int h[n]
, e[m]
, ne[m]
, w[m]
, idx;
int n, ans;
void
add(
int a,
int b)
//求以u為根的子樹的最大深度
intdfs
(int u,
int father)
ans =
max(ans, d1 + d2)
;return d1;
}int
main()
dfs(1,
-1);
cout << ans << endl;
return0;
}
To Heart 題解 樹的直徑
給定一棵樹,樹中每條邊都有乙個權值,樹中兩點之間的距離定義為連線兩點的路徑邊權之和。樹中最遠的兩個節點 兩個節點肯定都是葉子節點 之間的距離被稱為樹的直徑,連線這兩點的路徑被稱為樹的最長鏈。後者通常也可稱為直徑。我們設1號節點為根節點,那麼最短路徑則是到根節點最遠的乙個節點與次遠的乙個節點的距離之和...
To Heart 題解 樹的直徑
給定一棵樹,樹中每條邊都有乙個權值,樹中兩點之間的距離定義為連線兩點的路徑邊權之和。樹中最遠的兩個節點 兩個節點肯定都是葉子節點 之間的距離被稱為樹的直徑,連線這兩點的路徑被稱為樹的最長鏈。後者通常也可稱為直徑。我們設1號節點為根節點,那麼最短路徑則是到根節點最遠的乙個節點與次遠的乙個節點的距離之和...
牛客題霸 樹的直徑 C 題解 答案
牛客題霸 樹的直徑 c 題解 答案 給定一棵樹,求出這棵樹的直徑,即兩個節點距離的最大值。不知道大家聽沒聽過乙個結論 樹的直徑可以通過兩邊dfs找到 步驟 1.從任意一點進行dfs,然後找到乙個最長路徑,記錄最遠點u 2.然後從u再進行dfs,找最長路徑,記錄一點v。u,v 就是樹的直徑 證明 我們...