Codeforces Round #509 (Div. 2)--E. Tree Reconstruction

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37868325/article/details/82750091

题意:

是否存在n个点构成的树,切断其中一条边分成两部分的分别点的下标最大值,分别于给出的n-1种情况符合

思路:构造,这个树就是直的,没有分叉,然后,因为不论怎么分,n一定属于其中一部分,所以每种情况其中一个一定是n,所以,就对每对的令一半的最大值记录次数a[x],

首先从小到大判断,简单画一画图,1做最大值的次数一不超过1,1,2当最大值的和一定不超过2,1,2,3当最大值的和一定不超过3……否则输出NO,(可以先看后面再回来理解为什么不能超过)

符合以上所有情况就一定是YES。

从大到小判断 每个点

将n放在1位置,a[n-1]!=0,可以看作,点n-1与点n之间的边的条数(切断每条a[n]与a[n-1]之间的边,两部分最大值分别是n和n-1),若a[n-2]!=0,可以看成n-1与n-2之间的条数(切断每条a[n-1]与a[n-2]之间的边,两部分最大值分别是n和n-2)……

即若a[i]!=0,就相当于在上一个j(a[j]!=0)的点j与i点之间存在a[i]条边。

而其他的a[i]==0点,就可以看作在两个i点都大的点的中间,因为是从大到小放的,所以在放!=0的点时,中间产生的空格依次放就可以了(自己跟着样例写写就容易理解了)、

代码:(直接用别人的了,,就是个构造,代码倒是短。。)

#include<iostream>
using namespace std;
int a[1010],ans[1010];
int main()
{
	int n,i,cur=0,x,y,l1=1,l2=1;cin>>n;
	for (i=1;i<n;i++)
	{
		cin>>x>>y;if (x>y) swap(x,y);a[x]++;
		if (y!=n) {cout<<"NO";return 0;}
	}
	for (i=1;i<n;i++){cur+=a[i];if (cur>i) {cout<<"NO";return 0;}}
	cout<<"YES"<<endl;ans[1]=n;
	for (i=n-1;i;i--)
	{
		if (!a[i]) {while (ans[l2]) l2++;ans[l2]=i;continue;}
		l1+=a[i];ans[l1]=i;
	}
	for (i=1;i<n;i++) cout<<ans[i]<<' '<<ans[i+1]<<endl;
}

猜你喜欢

转载自blog.csdn.net/qq_37868325/article/details/82750091