hdu 2196 Computer
题目大意
给你一颗边带权值的树,求树上的每一点距离其最远的一个点的距离
分析
经典的树形DP题。由于对于一个节点来说,可能得到的距离最大的值的路径来自他的子树,或者从他的父节点过来,所以用两次DFS。
但是有个问题就是判断一个点的从父节点过来的最大值,那么如果他的父节点存的最大值正好是从该点过来的,那么就失去了从父节点过来的状态,所以要记录最大的两个值。
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<string> 5 #include<iostream> 6 #include<algorithm> 7 #include<set> 8 #define MAXN 20010 9 using namespace std; 10 struct Node 11 { 12 int v,w; 13 int next; 14 }node[MAXN]; 15 int tot,n; 16 int head[MAXN],maxn[MAXN],smaxn[MAXN],maxid[MAXN],smaxid[MAXN]; 17 void add(int u,int v,int w) 18 { 19 node[tot].v=v; 20 node[tot].w=w; 21 node[tot].next=head[u]; 22 head[u]=tot; 23 tot++; 24 } 25 void dfs1(int u,int p) 26 { 27 maxn[u]=0; 28 smaxn[u]=0; 29 for(int i=head[u];i!=-1;i=node[i].next) 30 { 31 int v=node[i].v; 32 if(v==p) 33 continue; 34 dfs1(v,u); 35 if(smaxn[u]<maxn[v]+node[i].w) 36 { 37 smaxn[u]=maxn[v]+node[i].w; 38 smaxid[u]=v; 39 if(smaxn[u]>maxn[u]) 40 { 41 swap(smaxn[u],maxn[u]); 42 swap(smaxid[u],maxid[u]); 43 } 44 } 45 } 46 } 47 void dfs2(int u,int p) 48 { 49 for(int i=head[u];i!=-1;i=node[i].next) 50 { 51 int v=node[i].v; 52 if(v==p) 53 continue; 54 if(v==maxid[u]) 55 { 56 if(node[i].w+smaxn[u]>smaxn[v]) 57 { 58 59 smaxn[v]=node[i].w+smaxn[u]; 60 smaxid[v]=u; 61 if(smaxn[v]>maxn[v]) 62 { 63 swap(smaxn[v],maxn[v]); 64 swap(smaxid[v],maxid[v]); 65 } 66 } 67 } 68 else 69 { 70 if(node[i].w+maxn[u]>smaxn[v]) 71 { 72 smaxn[v]=node[i].w+maxn[u]; 73 smaxid[v]=u; 74 if(smaxn[v]>maxn[v]) 75 { 76 swap(smaxn[v],maxn[v]); 77 swap(maxid[v],smaxid[v]); 78 } 79 } 80 } 81 dfs2(v,u); 82 83 } 84 } 85 int main() 86 { 87 while(scanf("%d",&n)!=EOF) 88 { 89 tot=0; 90 int v,w; 91 memset(head,-1,sizeof(head)); 92 for(int i=2;i<=n;i++) 93 { 94 scanf("%d %d",&v,&w); 95 add(i,v,w); 96 add(v,i,w); 97 } 98 dfs1(1,-1); 99 dfs2(1,-1); 100 for(int i=1;i<=n;i++) 101 printf("%d\n",maxn[i]); 102 103 } 104 return 0; 105 }
图是用邻接表保存的,不理解的可以看看我的上一篇博客