题意:
是否存在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;
}