1. 程式人生 > >codeforces round#509(div2) E. Tree Reconstruction

codeforces round#509(div2) E. Tree Reconstruction

這道題目的原則很簡單,就是把所有出現的x排個序,然後如果後面的比前面大就把後面的做父節點,相等就從沒出現過的數字中取出一個。

怎麼保證沒出現過的數字足夠滿足相等的數字呢?其實這道題已經保證了對於任何一個數字k,子樹最大值<=k的位置i不會超過k個,也就是說k放進去後面有多少個和k相等的數字,必定存在多少個沒出現過且小於k的數字(在更大數字出現之前)

比如 1 2 5 3 4就有5個子樹最大值小於等於5,而1 2 5 3 6 4則只有4個子樹最大值小於等於5.總之就是剩餘的數字肯定能把x數組裡面重復的數字填滿,程式裡面的排序過程用桶排序代替。book陣列實際上是x

#include<bits/stdc++.h>
using
namespace std; set<int> unused; int book[1010]; int in[1010]; int tot; int main() { int n; scanf("%d",&n); bool flag=true; for(int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); if(x>y) swap(x,y); if(y!=n) { flag
=false; } book[x]++; in[++tot]=x; } if(!flag) { printf("NO\n"); return 0; } int num=0; for(int i=1;i<n;i++) { num+=book[i]; if(num>i) { printf("NO\n"); return 0; } } printf(
"YES\n"); for(int i=1;i<n;i++) { unused.insert(i); } int last=-1; for(int i=1;i<n;i++) { if(book[i]) { unused.erase(i); book[i]--; if(last!=-1) { printf("%d %d\n",last,i); } last=i; } while(book[i]) { book[i]--; int now=*unused.begin(); printf("%d %d\n",last,now); last=now; unused.erase(unused.begin()); } } printf("%d %d\n",last,n); }

 

陣列