题意: 求每一个点的最远距离。ios
树形dp,作了两天,感受就是从子节点获得父节点。数组
此题要用到两次dfs, 第一次dfs1用来求全部节点在他子树范围内到叶子节点的最长距离和次长距离。dp1,和dp2ide
第二次dfs2 ,求f【】,若是dp1[s]==dp1[x]+len (s为父节点,x为子节点),则 x 在最长树的分支上,f[x]=max(f[s]+len,dp2[s]+len); spa
因此f【x】就等于f父节点加上到子节点的距离和父节点的次长加上到x节点的距离的二者的最大值。code
若是 不相等,则表明x节点不在父节点最长的分支上。则f【x】就等于f父节点到x节点的距离和父节点的最长距离加上到子节点距离 二者的最大值。blog
结果在max(f【】,dp1【】)string
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<iostream> 5 using namespace std; 6 const int Max=10001; 7 struct Point 8 { 9 int v,w; 10 }; 11 vector<Point>V[Max]; 12 int vis[Max]; 13 int f[Max],dp1[Max],dp2[Max]; 14 void init() 15 { 16 for(int i=1;i<Max;i++) 17 { 18 V[i].clear(); 19 } 20 memset(dp1,0,sizeof(dp1)); 21 memset(dp2,0,sizeof(dp2)); 22 memset(vis,0,sizeof(vis)); 23 memset(f,0,sizeof(f)); 24 } 25 void dfs1(int s) //全部节点在他子树范围内到叶子节点的最长距离和次长距离。dp1,和dp2 26 { 27 vis[s]=1; 28 for(int i=0;i<(int)V[s].size();i++) 29 { 30 int x=V[s][i].v; 31 int len=V[s][i].w; 32 if(!vis[x]) 33 { 34 dfs1(x); 35 int a=max(max(dp1[s],dp2[s]),dp1[x]+len); 36 if(a==dp1[s]) dp2[s]=max(dp2[s],dp1[x]+len); 37 else if(a==dp2[s]) dp2[s]=max(dp1[s],dp1[x]+len); 38 else dp2[s]=max(dp1[s],dp2[s]); 39 dp1[s]=a; 40 } 41 } 42 } 43 void dfs2(int s) //第二次dfs,求f数组。 44 { 45 vis[s]=1; 46 for(int i=0;i<(int)V[s].size();i++) 47 { 48 int x=V[s][i].v; 49 int len=V[s][i].w; 50 if(!vis[x]) 51 { 52 if(dp1[s]==dp1[x]+len) 53 f[x]=max(f[s]+len,dp2[s]+len); 54 else 55 f[x]=max(f[s]+len,dp1[s]+len); 56 dfs2(x); 57 } 58 } 59 } 60 int main() 61 { 62 //freopen("Input.txt","r",stdin); 63 int n,i; 64 while(~scanf("%d",&n)) 65 { 66 init(); 67 int a,b; 68 for(i=2;i<=n;i++) 69 { 70 scanf("%d%d",&a,&b); 71 Point tmp; 72 tmp.v=a;tmp.w=b; 73 V[i].push_back(tmp); 74 tmp.v=i; 75 V[a].push_back(tmp); 76 } 77 dfs1(1); 78 memset(vis,0,sizeof(vis)); 79 dfs2(1); 80 for(i=1;i<=n;i++) 81 printf("%d\n",max(dp1[i],f[i])); 82 } 83 return 0; 84 }