一、定義
對於一棵n個結點的無根樹,找到一條最長路徑。簡單說,要找到兩個點,使得它們的距離最遠。
二、求解
基本的求法是,先隨便找一個點作為根結點轉換為無根樹后,遍歷每一個點,找出當i為根結點時的子樹到葉子的最大距離d(j),在根據d(j)求出結點i作為根結點時整個樹的最長路徑,維護最長路徑即可。
1.狀態定義:d(i),i為根結點的子樹到葉子的最大距離。
2.狀態轉移方程:
d(i)=max{d(j)+w(i)}
#include<stdio.h> #include<stdlib.h> #define FORa(i,s,e) for(int i=s;i<=e;i++) #define FORs(i,s,e) for(int i=s;i>=e;i--) using namespace std; const int N=1000,INF=2147483647; int n,num_edge,ans,head[N+1],d[N+1]; struct Edge{ int next,to,dis; }edge[2*N]; inline void Add_edge(int from,int to,int dis) { edge[++num_edge]=(Edge){head[from],to,dis},head[from]=num_edge; } inline int max(int fa,int fb){return fa>fb?fa:fb;} inline int Dfs(int u,int fa,int dis) { int max1=0,max2=0;//子樹的鏈中的最大值與次大值 for(int i=head[u];i;i=edge[i].next) { if(edge[i].to!=fa) { Dfs(edge[i].to,u,dis+edge[i].to); if(d[edge[i].to]+edge[i].dis>max1) max2=max1,max1=d[edge[i].to]+edge[i].dis; else if(d[edge[i].to]+edge[i].dis>max2) max2=d[edge[i].to]+edge[i].dis; } } d[u]=max1; //考慮到將u作為根節點,更新子樹的鏈中的最大值與次大值 if(dis>max1) max2=max1,max1=dis; else if(dis>max2) max2=dis; ans=max(max1+max2,ans); } int main() { int from,to,dis; scanf("%d",&n); FORa(i,2,n) { scanf("%d%d%d",&from,&to,&dis); Add_edge(from,to,dis),Add_edge(to,from,dis); } Dfs(1,0,0); printf("%d",ans); return 0; } /*7 1 2 4 1 3 2 2 5 1 2 6 4 3 4 9 5 7 10 */