1. 程式人生 > >Gym - 101911G Tree Reconstruction

Gym - 101911G Tree Reconstruction

Statements

Monocarp has drawn a tree (an undirected connected acyclic graph) and then has given each vertex an index. All indices are distinct numbers from 11 to nn. For every edge eeof this tree, Monocarp has written two numbers: the maximum indices of the vertices of the two components formed if the edge ee (and only this edge) is erased from the tree.

Monocarp has given you a list of n−1n−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 nn (2≤n≤10002≤n≤1000) — the number of vertices in the tree.

Each of the next n−1n−1 lines contains two integers aiai and bibi each (1≤ai<bi≤n1≤ai<bi≤n) — the maximal indices of vertices in the components formed if the ii-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−1n−1 lines. Each of the last n−1n−1 lines should contain two integers xixiand yiyi (1≤xi,yi≤n1≤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

4
3 4
1 4
3 4

Output

YES
1 3
3 2
2 4

Input

3
1 3
1 3

Output

NO

Input

3
1 2
2 3

Output

NO

題意:n個點,給出n-1條邊  每條邊的左右部分的 最大節點編號  是否能還原這個樹

題解:首先給出的兩點一定要有一個是節點n,否則一定不符合

然後我們儲存一下較小的那個節點,排序,從小到大開始連線,若遇見一樣的,那就看是否有更小的節點沒有連線,這樣我們構造一個一條線的樹就可以了,詳見程式碼

#include<bits/stdc++.h>
using namespace std;
const int N=1100;
set<int> s;
int n,a[N],ans[N];
int main()
{
	int x,y;
	int flag=1;
	scanf("%d",&n);
	for(int i=1;i<n;i++)
	{
		scanf("%d%d",&x,&y);
		if(max(x,y)!=n) flag=0; // 判斷每對 是否有個節點 n 
		a[i]=min(x,y);
		s.insert(i);
	}
	if(!flag)
	{
		printf("NO\n");
		return 0;
	}
	sort(a+1,a+n);  // 把較小的節點 排序 
	
	s.insert(n);
	
	ans[1]=a[1];
	s.erase(a[1]);
	
	for(int i=2;i<n;i++)
	{
		if(a[i]==a[i-1]) // 若遇見一樣的  
		{
			int point=*s.begin(); // 判斷是否有小的點 沒有連線 
			if(point<a[i])
			{
				ans[i]=point;
				s.erase(point);
			}
			else
			{
				printf("NO\n");
				return 0;
			}
		}
		else
		{
			ans[i]=a[i];
			s.erase(a[i]);
		}
	}
	ans[n]=n;
	printf("YES\n");
	for(int i=1;i<n;i++) printf("%d %d\n",ans[i],ans[i+1]);
	return 0;
}