1. 程式人生 > >旅遊規劃

旅遊規劃

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>
using
namespace 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; }

最後喜歡的話不如來推薦,評論,關註三連。

不喜歡的話也昧著良心推薦一下吧!!!!

旅遊規劃