题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2196
思路:首先任意一次dfs求出树上最长直径的一个端点End,然后以该端点为起点再次dfs求出另一个端点,然后再次以求出的另一个端点为起点dfs,每次做dfs的时候都更新dist[](dist[u]表示u到树上任意节点的最远距离),可以证明树上任意某个节点到树上任意节点的最远距离的端点一定会是树上直径的两个端点之一。
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 using namespace std; 7 #define MAXN 10100 8 9 struct Edge{ 10 int v,w; 11 Edge(int vv,int ww):v(vv),w(ww){} 12 }; 13 14 int n; 15 int dist[MAXN],max_len,End; 16 vector<vector<Edge> >G; 17 18 void dfs(int u,int father,int len) 19 { 20 if(len>max_len)max_len=len,End=u; 21 for(int i=0;i<G[u].size();i++){ 22 int v=G[u][i].v,w=G[u][i].w; 23 if(v==father)continue; 24 dfs(v,u,len+w); 25 dist[v]=max(dist[v],len+w); 26 } 27 } 28 29 int main() 30 { 31 int u,w; 32 while(~scanf("%d",&n)){ 33 G.clear(); 34 G.resize(n+2); 35 for(int i=2;i<=n;i++){ 36 scanf("%d%d",&u,&w); 37 G[i].push_back(Edge(u,w)); 38 G[u].push_back(Edge(i,w)); 39 } 40 memset(dist,0,sizeof(dist)); 41 max_len=0; 42 dfs(1,-1,0); 43 dfs(End,-1,0);//分别从最长路的两端进行dfs. 44 dfs(End,-1,0); 45 for(int i=1;i<=n;i++){ 46 printf("%d\n",dist[i]); 47 } 48 } 49 return 0; 50 }