樹上直徑 樹上最遠點O n

2021-09-24 17:54:38 字數 1512 閱讀 8808

題目大意:對於一棵n個結點的無根樹,求出每個結點的最遠點,要求時間複雜度為o(n)。

對於乙個點,距離它最遠的點一定是直徑的端點。

證明:我們求直徑的時候,兩次dfs。

兩次bfs(或者dfs)

方法:先從任意一點p出發,找離它最遠的點q,再從點q出發,找離它最遠的點w,w到q的距離就是是的直徑

①若p已經在直徑上,根據樹的直徑的定義可知q也在直徑上且為直徑的乙個端點

②若p不在直徑上,我們用反證法,假設此時wq不是直徑,ab是直徑

—>若ab與pq有交點c,由於p到q最遠,那麼pc+cq>pc+ca,所以cq>ca,易得cq+cb>ca+cb,即cq+cb>ab,與ab是直徑矛盾,不成立,如下圖(其中ab,pq不一定是直線,畫成直線是為了方便):

—>若ab與pq沒有交點,m為ab上任意一點,n為pq上任意一點。首先還是np+nq>nq+mn+mb,同時減掉nq,得np>mn+mb,易知np+mn>mb,所以np+mn+ma>mb+ma,即np+mn+ma>ab,與ab是直徑矛盾,所以這種情況也不成立,如下圖:

那麼這個就已經證明了。

我們現在只需要把兩個端點求出來,然後對兩個端點進行兩次dfs,更新他們到端點的距離,然後取最大值的就行了。

#include

using

namespace std;

const

int maxn=

1e4+10;

struct e};

vector e[maxn]

;int dp[maxn][2

];int d, k;

int vis[maxn]

;int

dfs(

int u,

int s,

int f)

for(

int i=

0;i.size()

;i++)}

}int

main()

d=k=0;

dfs(1,

0,0)

; d1=k;

//第乙個端點

memset

(vis,0,

sizeof

(vis));

dfs(d1,0,

0);

d2=k;

//第二個端點

memset

(vis,0,

sizeof

(vis));

dfs(d2,0,

1);for

(int i=

1;i<=n;i++

)return0;

}

C 樹上的最遠點對

51nod 1766 vjudge n個點被n 1條邊連線成了一顆樹,給出 a b 和 c d 兩個區間,表示點的標號請你求出兩個區間內各選一點之間的最大距離,即你需要求出max dis i,j a i b,c j d ps 建議使用讀入優化 第一行乙個數字 n n 100000。第二行到第n行每行...

51NOD 1766 樹上的最遠點對

n 個點被n 1條邊連線成了一顆樹,邊有權值wi 有q 個詢問,給出 a b 和 c,d 兩個區間,表示點的標號請你求出兩個區間內各選一點之間的最大距離,即你需要求出 ma x 1 n,q 105,1 wi 104 可以發現最長路徑具有直徑的合併性質,即兩個區間選點的最長路徑端點一定是原本兩個區間最...

51nod1766 樹上的最遠點對

n個點被n 1條邊連線成了一顆樹,給出a b和c d兩個區間,表示點的標號請你求出兩個區間內各選一點之間的最大距離,即你需要求出max dis i,j a i b,c j d ps 建議使用讀入優化 第一行乙個數字 n n 100000。第二行到第n行每行三個數字描述路的情況,x,y,z 1 x,y...