G. Tree Reconstruction(构造)

G. Tree Reconstruction(构造)

思路:构造+贪心。

考虑去掉某条边后,其中一个连通分支的最大结点一定是 n n ,因此我们可以 n n 为根,连所有与他有该关系的结点,然后对于重复出现的关系,显然这个两个结点的之间的路径已定存在小于他们两个的结点,这样才能保证重复出现,且不改变该关系。

因此我们可以记录一下没有出现的结点然后从大到小插入题目给定关系的点对里,这样能保证其他点对有更小的结点可以插入。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e3+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
int n,cnt[N],a[N],tot,id;
PII ans[N]; 
int main(){
	scanf("%d",&n);
	int ok=1;
	for(int i=1;i<n;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		if(u>v) swap(u,v);
		if(v!=n) ok=0;
		cnt[u]++;
	}
	if(!ok) return puts("NO"),0;
	for(int i=1;i<n;i++)
		if(!cnt[i]) a[++tot]=i;
	for(int i=n-1;i;i--){
		if(!cnt[i]) continue;
		cnt[i]--;
		int u=i,v;
		while(cnt[i]--){
			int x=a[tot--];
			if(x>i){
				ok=0;
				break;
			}
			v=x;
			ans[++id]=make_pair(u,v);
			u=v;
		}
		if(!ok) break; 
		ans[++id]=make_pair(u,n);
	}
	if(!ok) return puts("NO"),0;
	puts("YES");
	for(int i=1;i<=id;i++)
	 printf("%d %d\n",ans[i].fi,ans[i].se);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45750972/article/details/107518724