一種是記錄以每個節點(u)為根,到其子樹的最遠葉節點的最大距離(dp[u][1])和次大距離(dp[u][0]); 這樣以該節點為根的子樹的直徑即為dp[u][0]+dp[u][1], 對於每個節點取max即為全樹的直徑;
void dfs(int u, intfa)
else
if (dp[u][0] < dp[v][1]+w)
dp[u][
0] = dp[v][1]+w;
}ans = max(ans, dp[u][1]+dp[u][0
]);}
另一種是只記錄最大距離,對於節點u,設dp[u]為以u為根的子樹的直徑,則dp[u]=max(dp[u], dp[u_son]+dist(u,u_son) ); 依舊對每個節點取max即為全樹的直徑;
void dfs(int u, intfa)
}
我們直接借助hdu2196這道題看看dfs如何求直徑以及樹上所有點到樹上最遠點的距離。隨便取乙個點做dfs,找到以這個點為根的樹的最遠的葉子節點,之後再以此葉子節點為根做dfs,找到距他最遠的節點及距離,這個距離即為樹的直徑。證明略,可用反證法。
下面說一下這道題中這三次dfs的作用。
第一次:以任意節點為根,根本目的是找到直徑的乙個端點a。在這個過程中記錄了這個起點到各個節點的距離,不過不影響。如果這個節點就是直徑的端點,那麼很好,如果不是,我們也會在後面更新。
第二次:以第一次找到的這個端點a為根,再做一次dfs,找到另乙個端點b,同時更新所有節點到a的距離。(如果第一次中任意選擇的那個節點是乙個端點的話,兩次dfs就可以結束了,但我們不能保證次次碰巧)
第三次dfs以b為根,更新所有節點到b的距離。由於樹上某個節點可以達到的最遠距離一定是它到直徑兩個端點的距離的較大值,故演算法結束。
1 #include 2using
namespace
std;
34 typedef long
long
ll;5
6const
int inf=0x3f3f3f3f;7
const
int maxn=1e4+50;8
struct
edge
11};
12 vectorg[maxn];
13int
dp[maxn],maxl,s;
1415
void dfs(int u,int f,int len)
20for(int i=0;i)26}
27int
main()
39 s=0; maxl=0
;40 dfs(1,0,0
);41 dfs(s,0,0
);42 dfs(s,0,0
);43
for(int i=1;i<=n;i++) cout45return0;
46 }
另外這題有一種dp的寫法,與上文所說的第一種dp有點像,有很多前輩的blog說的很詳細了,就不贅述了。
1 #include 2using
namespace
std;
34 typedef long
long
ll;5
6const
int inf=0x3f3f3f3f;7
const
int maxn=1e4+50;8
struct
edge
11};
12 vectorg[maxn];
13int dp[3
][maxn],id[maxn];
14//
id[u]: u在u的子樹中得到最大距離時,所經過的第乙個孩子結點
15//
dp[u][0]: u在u的所有子樹中獲得的最長距離
16//
dp[u][1]: u在u的所有子樹中獲得的次長距離
17//
dp[u][2]: u通過父親獲得的最長距離
18void dfs1(int u,int
f)27}28
for(int i=0;i//
get次長
29int to=g[u][i].to,w=g[u][i].w;
30if(to==f||id[u]==to) continue
;31 dp[1][u]=max(dp[1][u],dp[0][to]+w);32}
33}34void dfs2(int u,int
f)45}46
47int
main()
59 dfs1(1,0
);60 dfs2(1,0
);61
for(int i=1;i<=n;i++)
62 cout<0][i],dp[2][i])<64return0;
65 }
求樹的直徑
歡迎來踩本人部落格 樹的直徑 就是樹上最長路 方法 求兩邊dfs即可 步驟 1.從任意一點進行dfs,然後找到乙個最長路徑,記錄最遠點u 2.然後從u再進行dfs,找最長路徑,記錄一點v。u,v 就是樹的直徑 第四屆藍橋杯a組 證明 我們可以看出圖中,樹的直徑是 4 2 5 長度為9.我們一開始選定...
求樹的直徑
歡迎來踩本人部落格 樹的直徑 就是樹上最長路 方法 求兩邊dfs即可 步驟 1.從任意一點進行dfs,然後找到乙個最長路徑,記錄最遠點u 2.然後從u再進行dfs,找最長路徑,記錄一點v。u,v 就是樹的直徑 第四屆藍橋杯a組 證明 我們可以看出圖中,樹的直徑是 4 2 5 長度為9.我們一開始選定...
求樹的直徑
由於之前寫了一篇部落格,用到了樹的直徑卻沒有求。在咕咕咕了n多天之後決定寫這篇部落格。樹的直徑就是樹中最長的一條路。求樹的直徑我只會一種方法 據說dalao都會2種 隨便找乙個點跑一遍最短路,找到離他最遠的節點a,然後從a節點繼續跑最短路,再次找到乙個離a最遠的節點b,a和b分別是直徑的兩個端點,他...