標籤:
題目大意
給你一顆邊帶權值的樹,求樹上的每一點距離其最遠的一個點的距離
分析
經典的樹形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 }
圖是用鄰接表儲存的,不理解的可以看看我的上一篇部落格
hdu 2196 Computer