旅遊規劃
阿新 • • 發佈:2018-08-20
align 最長鏈 tput char enter utc time i++ clu
試題描述 |
W 市的交通規劃出現了重大問題,市政府下定決心在全市各大交通路口安排疏導員來疏導密集的車流。但由於人員不足,W 市市長決定只在最需要安排人員的路口安排人員。具體來說,W 市的交通網絡十分簡單,由 n 個交叉路口和 n−1 條街道構成,交叉路口路口編號依次為 0,1,?,n−1 。任意一條街道連接兩個交叉路口,且任意兩個交叉路口間都存在一條路徑互相連接。 經過長期調查,結果顯示,如果一個交叉路口位於 W 市交通網最長路徑上,那麽這個路口必定擁擠不堪。所謂最長路徑,定義為某條路徑 p=(v1,v2,v3,……,vk),路徑經過的路口各不相同,且城市中不存在長度大於 k 的路徑,因此最長路徑可能不唯一。因此 W 市市長想知道哪些路口位於城市交通網的最長路徑上。
|
輸入 |
第一行一個整數 n;之後 n−1 行每行兩個整數 u,v,表示 u 和 v 的路口間存在著一條街道。 |
輸出 |
包括若幹行,每行包括一個整數——某個位於最長路徑上的路口編號。為了確保解唯一,請將所有最長路徑上的路口編號按編號順序由小到大依次輸出。 |
輸入示例 |
10 0 1 0 2 0 4 0 6 0 7 1 3 2 5 4 8 6 9 |
輸出示例 |
0 1 2 3 4 5 6 8 9 |
其他說明 |
數據範圍:對於全部數據 1 <= n <= 2×100 000?? 。 |
看註釋
#include<iostream> #include<algorithm> #include<cstring> #include<string> #include<cstdio> #include<cstdlib> #include<cmath> usingnamespace std; inline int rd() { int x=0,f=1; char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch==‘-‘) f=-1; for(;isdigit(ch);ch=getchar()) x=x*10+ch-‘0‘; return x*f; } inline void write(int x) { if(x<0) putchar(‘-‘),x=-x; if(x>9) write(x/10); putchar(x%10+‘0‘); return ; } int n; int head[400006],to[400006],nxt[400006];//數組應定要開夠!!!!!!!!!! int total=0; void add(int x,int y) { total++; to[total]=y; nxt[total]=head[x]; head[x]=total; return ; } int fir[400006],sec[400006];//fir[i]存的是以i為根的最長鏈,sec[i]是次長鏈 int s1[400006],s2[400006];//分別存最長連和次長鏈是從那個點轉移的 int ans=0;//最長鏈長度 int dfs(int x,int la)//x是當前點,la是他的父親節點 { for(int e=head[x];e;e=nxt[e]) { int h=to[e]; if(h!=la) { int d=dfs(h,x)+1; if(d>fir[x]) { //註意在給最長鏈賦值時,要把原來最長鏈在的額支賦給次長鏈 sec[x]=fir[x]; s2[x]=s1[x]; fir[x]=d; s1[x]=h; } else if(d>sec[x]) { sec[x]=d; s2[x]=h; } } } ans=max(ans,fir[x]+sec[x]);//因為最長鏈和次長鏈從不同子樹轉移,所以書上最長鏈為兩個的和 return fir[x]; } int g[400006]; void dp(int x,int la) { if(x!=0) { /* 玄學存 因為fir和sec存的是由子樹轉移的值 所以就忽略了一種特殊情況 例子: * | * | * / * * / * * 所以很明顯,我們需要一個數組來存上面的最長鏈 */ if(x!=s1[la]) g[x]=max(fir[la]+1,g[la]+1);//不能從父親節點直接轉移,因為可能是fir,所以用到了s1和s2 else g[x]=max(sec[la]+1,g[la]+1); } for(int e=head[x];e;e=nxt[e]) if(to[e]!=la) dp(to[e],x); } int main() { n=rd(); for(int i=1;i<n;i++) { int x,y; x=rd(); y=rd(); add(x,y);//雙向存邊,因為是無向圖 add(y,x); } dfs(0,0);//註意初值,下標從0開始 dp(0,0); for(int i=0;i<n;i++) if(g[i]+fir[i]==ans||fir[i]+sec[i]==ans) printf("%d\n",i);//輸出節點(調了好久QAQ) return 0; }
最後喜歡的話不如來推薦,評論,關註三連。
不喜歡的話也昧著良心推薦一下吧!!!!
旅遊規劃