codeforces—1014E. Tree Reconstruction(构造+思维)

 

E. Tree Reconstruction

time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard output

Monocarp has drawn a tree (an undirected connected acyclic graph) and then has given each vertex an index. All indices are distinct numbers from 1

to n. For every edge e of this tree, Monocarp has written two numbers: the maximum indices of the vertices of the two components formed if the edge e

(and only this edge) is erased from the tree.

Monocarp has given you a list of n−1

pairs of numbers. He wants you to provide an example of a tree that will produce the said list if this tree exists. If such tree does not exist, say so.

Input

The first line contains one integer n

(2≤n≤1000

) — the number of vertices in the tree.

Each of the next n−1

lines contains two integers ai and bi each (1≤ai<bi≤n) — the maximal indices of vertices in the components formed if the i

-th edge is removed.

Output

If there is no such tree that can produce the given list of pairs, print "NO" (without quotes).

Otherwise print "YES" (without quotes) in the first line and the edges of the tree in the next n−1

lines. Each of the last n−1 lines should contain two integers xi and yi (1≤xi,yi≤n

) — vertices connected by an edge.

Note: The numeration of edges doesn't matter for this task. Your solution will be considered correct if your tree produces the same pairs as given in the input file (possibly reordered). That means that you can print the edges of the tree you reconstructed in any order.

Examples

Input

Copy

4
3 4
1 4
3 4

Output

Copy

YES
1 3
3 2
2 4

Input

Copy

3
1 3
1 3

Output

Copy

NO

Input

Copy

3
1 2
2 3

Output

Copy

NO

Note

Possible tree from the first example. Dotted lines show edges you need to remove to get appropriate pairs.

题意:

 

给了n,代表n个点。然后n-1行,代表,分别去掉每一条边,分成的两个连通分量中的节点中最大的节点序号。
输出你构造的树。

思路:

首先,每一次切分最大的都要有n。否则直接输出no

然后就是构造了,就是以n为根节点,从大到小每个点,将那些去掉边之后,从来都没有在最大点中出现的那些点放到n和i中间,

以一条链的形式这样接上。

 

大概就是这样子。。

之所以在代码中会有v>i就输出no,是因为任何不是最大值的这些点,就说明他们肯定比当前链的上下端点的值要小。有人说当叶子不就行了,当叶子的话那么一定在最大值的这些点中,矛盾了。

要理解建图思想。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1005;
vector<int> ansl,ansr;
int x,y,s[N],top=0,n,a[N];
int main()
{
	scanf("%d",&n);
	for (int i=1;i<n;i++)
	 {
		scanf("%d%d",&x,&y);
		if (x==n)a[y]++;
		else if (y==n)a[x]++;
		else
		 {
		 	puts("NO");
			return 0;
		 }
	 }
	for (int i=1;i<n;i++)
	 if (!a[i])
        s[++top]=i;///处于两边的点。。在两边都不大
	
	for (int i=n-1;i;i--)
    {
		if (!a[i])
            continue;
		a[i]--;///把他放在叶子上。。。相当于有一个无用了
		int u=n,v;
		while (a[i]--)
        {
			v=s[top--];
			if (v>i)///这个时候无论怎么凑都不会凑出这种情况。
                ///因为这个时候如果有一个大于他的话,那么切割之后最大的就不是当前的值了。。
                ///因为当前我想让他夹在n和i之间。而i是由大到小进行枚举的。
            {puts("NO");return 0;}
            
            ansl.push_back(u);
            ansr.push_back(v);
            u=v;
        }
		ansl.push_back(u);
		ansr.push_back(i);
    }
	puts("YES");
	for (int i=0;i<n-1;i++)
        printf("%d %d\n",ansl[i],ansr[i]);
	return 0;
}

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值