http://codeforces.com/contest/1041/problem/E
右点必为n 否则就no
将左点存起来并记录出现次数 以这些点为叶节点 将剩下的为出现的点填到叶节点与根节点n之间
比赛就掉了一句j++ 攒人品吧
#include<bits/stdc++.h>
using namespace std;
vector <int> edge[1010];
int e[1010][1010];
int book[1010],pre1[1010],pre2[1010];
int n,len1,len2;
int main()
{
int u,v,i,j,flag,sz;
scanf("%d",&n);
book[n]=1;
flag=1;
for(i=1;i<=n-1;i++)
{
scanf("%d%d",&u,&v);
book[u]++;
if(v!=n) flag=0;
}
if(flag)
{
for(i=1;i<=n-1;i++)
{
if(book[i]==0) pre1[++len1]=i;
else pre2[++len2]=i;
}
sort(pre1+1,pre1+len1+1);
sort(pre2+1,pre2+len2+1);
/*
for(i=1;i<=len1;i++) printf("%d ",pre1[i]);
printf("\n");
for(i=1;i<=len2;i++) printf("%d ",pre2[i]);
printf("\n");
*/
for(i=1,j=1;i<=len2;i++)
{
if(book[pre2[i]]>1)
{
book[pre2[i]]--;
while(book[pre2[i]]>0&&j<=len1)
{
if(pre2[i]<pre1[j])
{
flag=0;
break;
}
edge[pre2[i]].push_back(pre1[j]);
book[pre2[i]]--;
j++;
}
if(flag==0) break;
}
else e[pre2[i]][n]=1;
}
if(flag)
{
for(i=1;i<=n;i++)
{
sz=edge[i].size();
if(sz>0)
{
/*
printf("*%d*\n",sz);
for(j=0;j<sz;j++) printf("%d ",edge[i][j]);
printf("\n");
*/
for(j=0;j+1<sz;j++)
{
e[edge[i][j]][edge[i][j+1]]=1;
}
e[i][edge[i][0]]=1,e[n][edge[i][sz-1]]=1;
}
}
printf("YES\n");
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(e[i][j])
{
printf("%d %d\n",i,j);
}
}
}
}
else printf("NO\n");
}
else printf("NO\n");
return 0;
}