1. 程式人生 > >Computer HDU - 2196

Computer HDU - 2196

感覺 ret max 子節點 printf get targe 記錄 names

Computer HDU - 2196

題意:求以樹上任一點為端點的最長鏈。註意,讀入的不是邊表,而是每個節點(除了1號,它是根節點)的父親和與父親間邊的長度。

方法:

從每個端點出發的最長鏈,第一種是向下(向子節點)走,第二種是向父節點走。分別處理即可。(具體看程序)

(感覺做法一點也不優美....最長鏈次長鏈什麽鬼...)

錯誤(本地):少了23行,沒有將原來最長鏈更新到次長鏈上

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace
std; 5 struct Edge 6 { 7 int to,next,w; 8 }e[20100]; 9 int f1[10100],ne,fa[10100],a1[10100],a2[10100],b1[10100],ww[10100],b2[10100],ansu[10100]; 10 //a1[i],b1[i]分別記錄節點i向下最長鏈的長度,節點i向下最長鏈所經過的i的子節點編號 11 //a2[i],b2[i]分別記錄節點i向下次長鏈的長度(保證除了節點i以外,不與最長鏈有公共節點),節點i向下次長鏈所經過的自身的子節點編號 12 //ww[i]記錄節點i到父節點的邊的權值 13 //ansu[i]記錄節點i向上走的最長鏈
14 int n; 15 void dfs(int x,int fa) 16 { 17 for(int k=f1[x];k!=0;k=e[k].next) 18 if(e[k].to!=fa) 19 { 20 dfs(e[k].to,x);//先求出子節點向下的a1,b1,a2,b2,再用子節點的來更新自身的 21 if(a1[e[k].to]+e[k].w>a1[x])//如果比已知最長鏈長 22 { 23 a2[x]=a1[x],b2[x]=b1[x];//
那麽新的次長鏈就是已知最長鏈 24 a1[x]=a1[e[k].to]+e[k].w,b1[x]=e[k].to;//新的最長鏈就是自身指向這個子節點的邊再加上子節點向下的最長鏈形成的鏈 25 } 26 else if(a1[e[k].to]+e[k].w>a2[x])//如果不比已知最長鏈長,但比已知次長鏈長 27 a2[x]=a1[e[k].to]+e[k].w,b2[x]=e[k].to;//新的次長鏈就是自身指向這個子節點的邊再加上子節點向下的最長鏈形成的鏈 28 } 29 } 30 void dfs2(int x,int fa)//分別為當前節點編號和當前節點父親編號 31 { 32 if(fa!=0)//如果為根節點,那麽沒有向上的鏈,否則就有 33 { 34 int t1; 35 if(x==b1[fa]) 36 t1=a2[fa]; 37 else 38 t1=a1[fa];//t1表示父親節點向下的最長鏈長度。如果父親節點向下的最長鏈經過x,那麽t1變為父親節點向下的次長鏈長度 39 //就是父親節點的向下的不經過x的最長鏈長度 40 ansu[x]=max(t1,ansu[fa])+ww[x]; 41 //當前節點向上的最長鏈,就是當前節點指向父親的邊再加上父親節點向上的最長鏈形成的鏈,與當前節點指向父親的邊加上t1形成的鏈,其中較長的一條 42 } 43 for(int k=f1[x];k!=0;k=e[k].next) 44 if(e[k].to!=fa) 45 dfs2(e[k].to,x);//這一次要先求出父節點的才能求出子節點的,與第一個dfs()不一樣 46 } 47 int main() 48 { 49 int i,x,y; 50 while(scanf("%d",&n)==1) 51 { 52 ne=0; 53 memset(f1,0,sizeof(f1)); 54 memset(fa,0,sizeof(fa)); 55 memset(a1,0,sizeof(a1)); 56 memset(a2,0,sizeof(a2)); 57 memset(ansu,0,sizeof(ansu)); 58 for(i=2;i<=n;i++) 59 { 60 scanf("%d%d",&x,&y); 61 e[++ne].to=x; 62 e[ne].next=f1[i]; 63 e[ne].w=y; 64 f1[i]=ne; 65 e[++ne].to=i; 66 e[ne].next=f1[x]; 67 e[ne].w=y; 68 f1[x]=ne; 69 ww[i]=y; 70 } 71 dfs(1,0);//求出所有節點向下走的最長鏈與次長鏈 72 dfs2(1,0);//求出所有節點向上走的最長鏈 73 for(i=1;i<=n;i++) 74 printf("%d\n",max(a1[i],ansu[i]));//最後答案就是某個點向下、向上走的最長鏈中較長的一條 75 } 76 77 return 0; 78 }

Computer HDU - 2196