【codeforces】1041E Tree Reconstruction【构造】
E. Tree Reconstruction
【题目描述】
【题解】
最后所有可行答案中肯定有一种是链。所以我们只需要构造条链就可以了。
首先我们任意切开一条边,肯定有一个联通块的最大值是n,然后n-1肯定会出现一次。否则就输NO。
我们定义关键点是在读入中出现过的点。
肯定先从小的开始,这个关键点的出现次数就是这个关键点与下个关键点之间的距离,当然这中间连的点一定要小于两边的点。
这棵树就是n为根节点,关键点大小依次递减的链。
代码如下
#include<queue>
#include<cstdio>
#include<cctype>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int MAXN=1005;
int n,que[MAXN],tl,Num[MAXN];
struct xcw{int x,y;}a[MAXN];
bool vis[MAXN];
int read(){
int ret=0;char ch=getchar();bool f=1;
for(;!isdigit(ch);ch=getchar()) f^=(ch^'-');
for(; isdigit(ch);ch=getchar()) ret=(ret<<1)+(ret<<3)+ch-48;
return f?ret:-ret;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("prob.in","r",stdin);
freopen("prob.out","w",stdout);
#endif
scanf("%d",&n);
bool t1=1,t2=0;
for(int i=1;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
if(x==y) t1=0;
if(x==n) que[i]=y;else que[i]=x;
if(x!=n&&y!=n) t1=0;
if(x==n-1||y==n-1) t2=1;
}
if(t1==0||t2==0){printf("NO\n");return 0;}
sort(que+1,que+n);que[0]=tl=0;
for(int i=1,j=1;i<n;i=j){
que[++tl]=que[i];vis[que[i]]=1;
for(j=i+1;j<=n&&que[i]==que[j];j++);
Num[tl]=j-i;
}
que[tl+1]=n;
int Now=1,tot=0;
for(int i=1;i<=tl;i++){
int lst=que[i],Y=Num[i]-1;
while(Num[i]-1){
while(vis[Now]&&Now<=n) Now++;vis[Now]=1;
if(Now>que[i]){printf("NO\n");return 0;}
a[++tot]=(xcw){lst,Now};lst=Now;Num[i]--;
}
if(!Y) a[++tot]=(xcw){que[i+1],que[i]};else a[++tot]=(xcw){que[i+1],Now};
}
if(tot!=n-1){printf("NO\n");return 0;}
printf("YES\n");
for(int i=1;i<=tot;i++) printf("%d %d\n",a[i].x,a[i].y);
return 0;
}