51nod 1273 旅行計劃——思維題
阿新 • • 發佈:2017-08-19
並且 可以轉化 col 輸出 技術分享 aps 之間 closed 節點
某個國家有N個城市,編號0 至 N-1,他們之間用N - 1條道路連接,道路是雙向行駛的,沿著道路你可以到達任何一個城市。你有一個旅行計劃,這個計劃是從編號K的城市出發,每天到達一個你沒有去過的城市,並且旅途中經過的沒有去過的城市盡可能的多(如果有2條路線,經過的沒有去過的城市同樣多,優先考慮編號最小的城市),直到所有城市都觀光過一遍。現在給出城市之間的交通圖T,以及出發地點K,你來設計一個旅行計劃,滿足上面的條件。例如:
(K = 2)
第1天 從2到0 (城市 1 和 0 變成去過的)
第2天 從0到6 (城市 4 和 6 變成去過的)
第3天 從6到3 (城市 3 變成去過的)
第4天 從3到5 (城市 5 變成去過的)
上圖的輸入數據為:0 1 2 2 1 4。共7個節點,除節點0之外,共6行數據。
第1個數0表示1到0有1條道路。
第2個數1表示2到1有1條道路。
Input
第1行:2個數N,K(1 <= N <= 50000, 0 <= K <= N - 1)
第2 - N + 1行:每行一個數,表示節點之間的道路。
Output
輸出旅行的路線圖,即每天到達的城市編號。
Input示例
7 2
0
1
2
2
1
4
Output示例
2 0 6 3 5
————————————————————————————————————————————————————
以下搬自51nod題解考慮將樹根設為K,觀察到以下結論:
1. 每次必然會走到葉子,否則可以繼續向下走到葉子,使得訪問的點增多。
2. 考慮每次訪問到的未訪問的點,一定是與葉子相連的、在葉子到點K路徑上的一條連續的鏈,
所以問題可以轉化為:
令每個葉子分別支配一條鏈,使得標號小的點盡量支配多的點,最後根據支配的點數多少、標號大小依次訪問。
以做法可以是樹上貪心,從深到淺依次確定每個點被其子樹裏哪個葉子支配,
然後使得那個點的支配點個數加一,
最後用基數排序排出支配點數降序、標號大小升序即可。
當然我懶 所以寫的是sort代替基排
#include<cstdio> #include<cstring> #includeView Code<algorithm> using namespace std; const int M=50007; int read(){ int ans=0,f=1,c=getchar(); while(c<‘0‘||c>‘9‘){if(c==‘-‘) f=-1; c=getchar();} while(c>=‘0‘&&c<=‘9‘){ans=ans*10+(c-‘0‘); c=getchar();} return ans*f; } char s[23];int len; inline void outx(int x) { if(!x){putchar(‘0‘);return;} while(x)s[++len]=x%10,x/=10; while(len)putchar(s[len--]+48); } int T,n,rt; int first[M],cnt; struct node{int to,next;}e[M*2]; void ins(int a,int b){e[++cnt]=(node){b,first[a]}; first[a]=cnt;} void insert(int a,int b){ins(a,b); ins(b,a);} int sum; struct pos{int d,pos;}p[M]; bool cmp(pos a,pos b){return a.d!=b.d?a.d>b.d:a.pos<b.pos;} void dfs(int x,int fa,int deep){ bool f=true; for(int i=first[x];i;i=e[i].next){ int now=e[i].to; if(now!=fa) f=false,dfs(now,x,deep+1); } if(f&&x!=rt) p[++sum].pos=x,p[sum].d=deep; } int vis[M]; struct Ans{int h,pos;}q[M]; bool qcmp(Ans a,Ans b){return a.h!=b.h?a.h>b.h:a.pos<b.pos;} int find(int x,int fa){ if(vis[x]||x==rt) return 1; for(int i=first[x];i;i=e[i].next){ int now=e[i].to; if(now==fa) continue; if(find(now,x)) return T++,vis[x]=1,1; } return 0; } int main() { int x; n=read(); rt=read(); for(int i=1;i<n;i++) x=read(),insert(i,x); for(int i=1;i<=n;i++) p[i].pos=i; dfs(rt,-1,0); sort(p+1,p+1+sum,cmp); for(int i=1;i<=sum;i++){ q[i].pos=p[i].pos; T=0; find(p[i].pos,-1); q[i].h=T; } sort(q+1,q+1+sum,qcmp); printf("%d\n",rt); for(int i=1;i<=sum;i++) printf("%d\n",q[i].pos); return 0; }
51nod 1273 旅行計劃——思維題