Problem:
Score : 900 points

Problem Statement

Takahashi has an ability to generate a tree using a permutation (p_1,p_2,...,p_n) of (1,2,...,n), in the following process:

First, prepare Vertex 1, Vertex 2, ..., Vertex N.
For each i=1,2,...,n, perform the following operation:

If p_i = 1, do nothing.

If p_i \neq 1, let j' be the largest j such that p_j < p_i. Span an edge between Vertex i and Vertex j'.

Takahashi is trying to make his favorite tree with this ability.
His favorite tree has n vertices from Vertex 1 through Vertex n, and its i-th edge connects Vertex v_i and w_i.
Determine if he can make a tree isomorphic to his favorite tree by using a proper permutation.
If he can do so, find the lexicographically smallest such permutation.

Notes

For the definition of isomorphism of trees, see wikipedia. Intuitively, two trees are isomorphic when they are the "same" if we disregard the indices of their vertices.

Constraints

2 \leq n \leq 10^5

1 \leq v_i, w_i \leq n

The given graph is a tree.

Input

Input is given from Standard Input in the following format:

n
v_1 w_1
v_2 w_2
:
v_{n-1} w_{n-1}

Output

If there is no permutation that can generate a tree isomorphic to Takahashi's favorite tree, print -1.
If it exists, print the lexicographically smallest such permutation, with spaces in between.

Sample Input 1

6
1 2
1 3
1 4
1 5
5 6

Sample Output 1

1 2 4 5 3 6

If the permutation (1, 2, 4, 5, 3, 6) is used to generate a tree, it looks as follows:

This is isomorphic to the given graph.

Sample Input 2

6
1 2
2 3
3 4
1 5
5 6

Sample Output 2

1 2 3 4 5 6

Sample Input 3

15
1 2
1 3
2 4
2 5
3 6
3 7
4 8
4 9
5 10
5 11
6 12
6 13
7 14
7 15

Sample Output 3

-1

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

// #includes {{{
#include <bits/stdc++.h>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)(n);++i)
#define RREP(i,a,b) for(int i=(int)(a);i<(int)(b);++i)
#define FOR(i,c) for(__typeof((c).begin()) i=(c).begin();i!=(c).end();++i)
#define LET(x,a) __typeof(a) x(a)
//#define IFOR(i,it,c) for(__typeof((c).begin())it=(c).begin();it!=(c).end();++it,++i)
#define ALL(c) (c).begin(), (c).end()
#define MP make_pair

#define EXIST(e,s) ((s).find(e)!=(s).end())

#define RESET(a) memset((a),0,sizeof(a))
#define SET(a) memset((a),-1,sizeof(a))
#define PB push_back
#define DEC(it,command) __typeof(command) it=command

//debug
#define dump(x)  cerr << #x << " = " << (x) << endl;
#define debug(x) cerr << #x << " = " << (x) << " (L" << __LINE__ << ")" << " " << __FILE__ << endl;
#define debug_v(x) cerr << #x << " = [";REP(__ind,(x).size()){cerr << (x)[__ind] << ", ";}cerr << "] (L" << __LINE__ << ")" << endl;

#define whole(f,x,...) ([&](decltype((x)) whole) { return (f)(begin(whole), end(whole), ## __VA_ARGS__); })(x)

typedef long long Int;
typedef unsigned long long uInt;
typedef long double rn;

template<class T>
T inf(){
	return numeric_limits<T>::has_infinity?numeric_limits<T>::infinity():(numeric_limits<T>::max()/2);
}

typedef pair<int,int> pii;

/*
#ifdef MYDEBUG
#include"debug.h"
#include"print.h"
#endif
*/
// }}}

//{{{ io
FILE *file_in=stdin,*file_out=stdout;
#define fin normal_in
#define fout normal_out
//const char fname[]="";
//FILE *fin=fopen(fname,"r"),*fout=fopen(fname,"w");
#ifdef __MINGW32__
#define LLD "%I64d"
#define LLU "%I64u"
#else
#define LLD "%lld"
#define LLU "%llu"
#endif
struct NORMAL_IN{
	bool cnt;
	NORMAL_IN():cnt(true){}
	operator int() const {return cnt;}
#define endl "\n"
	NORMAL_IN& operator>>(int &n){cnt=fscanf(file_in,"%d",&n)!=EOF;return *this;}
	NORMAL_IN& operator>>(unsigned int &n){cnt=fscanf(file_in,"%u",&n)!=EOF;return *this;}
	NORMAL_IN& operator>>(long long &n){cnt=fscanf(file_in,LLD,&n)!=EOF;return *this;}
	NORMAL_IN& operator>>(unsigned long long &n){cnt=fscanf(file_in,LLU,&n)!=EOF;return *this;}
	NORMAL_IN& operator>>(double &n){cnt=fscanf(file_in,"%lf",&n)!=EOF;return *this;}
	NORMAL_IN& operator>>(long double &n){cnt=fscanf(file_in,"%Lf",&n)!=EOF;return *this;}
	NORMAL_IN& operator>>(char *c){cnt=fscanf(file_in,"%s",c)!=EOF;return *this;}
	NORMAL_IN& operator>>(string &s){
		s.clear();
		for(bool r=false;;){
			const char c=getchar();
			if(c==EOF){ cnt=false; break;}
			const int t=isspace(c);
			if(!r and !t)r=true;
			if(r){
				if(!t)s.push_back(c);
				else break;
			}
		}
		return *this;
	}
	template<class T>
		NORMAL_IN& operator>>(vector<T> &v){
			int n;fscanf(file_in,"%d",&n);
			REP(i,n){
				T t;*this>>t;
				v.push_back(t);
			}
			return *this;
		}
} normal_in;

struct NORMAL_OUT{
	NORMAL_OUT& operator<<(const int &n){fprintf(file_out,"%d",n);return *this;}
	NORMAL_OUT& operator<<(const unsigned int &n){fprintf(file_out,"%u",n);return *this;}
	NORMAL_OUT& operator<<(const long long &n){fprintf(file_out,LLD,n);return *this;}
	NORMAL_OUT& operator<<(const unsigned long long &n){fprintf(file_out,LLU,n);return *this;}
	NORMAL_OUT& operator<<(const double &n){fprintf(file_out,"%lf",n);return *this;}
	NORMAL_OUT& operator<<(const long double &n){fprintf(file_out,"%Lf",n);return *this;}
	NORMAL_OUT& operator<<(const char c[]){fprintf(file_out,"%s",c);return *this;}
	NORMAL_OUT& operator<<(const string &s){fprintf(file_out,"%s",s.c_str());return *this;}
} normal_out;
struct ERR_OUT{
	template<class T>
		ERR_OUT& operator<<(const T &a){
			cerr<<"\x1b[7m"<<a<<"\x1b[m";
			return *this;
		}
} ferr;
//}}}

//{{{ Graph<Weight> g(size); addEdge(g,{src,dst},weight); matrix<Weight> A(n,m);
typedef int Node;
template<class Weight>
struct edge {
	int src, dst;
	Weight weight;
	int rev;
	edge(int src, int dst, Weight weight=1,int rev=-1) :
		src(src), dst(dst), weight(weight), rev(rev){ }
};
template<class Weight>
bool operator < (const edge<Weight> &e, const edge<Weight> &f) {
	return e.weight != f.weight ? e.weight > f.weight : // !!INVERSE!!
		e.src != f.src ? e.src < f.src : e.dst < f.dst;
}
//typedef vector<edge> edges;
//typedef vector<edges> Graph;
 
template<class Weight>
struct matrix:vector<vector<Weight> >{
	matrix(const array<int,2> &a, Weight w=0):vector<vector<Weight> >(a[0],vector<Weight>(a[1],w)){}
	matrix(const array<int,1> &a, Weight w=0):vector<vector<Weight> >(a[0],vector<Weight>(a[0],0)){}
	matrix(){}
};
 
template<class Weight>
struct graph:vector<vector<edge<Weight> > >{
	Weight inf{::inf<Weight>()};
	graph(){}
	graph(const int &n):vector<vector<edge<Weight> > >(n){}
	void _add_edge(int from, int to, Weight w, int rev=-1){
		if((int)this->size() < from + 1)this->resize(from + 1);
		this->at(from).push_back(edge<Weight>(from,to,w,rev));
	}
};
//add bi-directional edge
template<class Weight>
void addBiEdge(graph<Weight> &g, const pair<int,int> &e, Weight w=1){
	const int &from = e.first, &to = e.second;
	g._add_edge(from,to,w,g[to].size());
	g._add_edge(to,from,w,g[from].size()-1);
}
//add directional edge
template<class Weight>
void addEdge(graph<Weight> &g, const pair<int,int> &e, Weight w=1){
	const int &from = e.first, &to = e.second;
	g._add_edge(from,to,w);
}
 
typedef int Weight;
typedef edge<Weight> Edge;
typedef graph<Weight> Graph;
typedef matrix<Weight> Matrix;
 
#ifdef DEBUG
#include"graph/graphviz.h"
#endif
//}}}


//{{{ Print functions
// Input/Output
template<class T>
void matrix_out(const vector<vector<T> > &x){
	REP(i,x.size()){
		REP(j,x[0].size()){
			cout<<x[i][j]<<"\t";
		}
		cout<<endl;
	}
}

template<class U,class S,class T>
U &operator<<(U &os, const pair<S,T> &p){
	os<<"("<<p.first<<", "<<p.second<<")";
	return os;
}

void printBit(int b,int k=-1){
	if(k==-1){
		int bb=1,i=0;
		while(bb){
			if(b&bb)k=i;
			bb<<=1;i++;
		}
	}
	REP(ct,k){
		cout<<b%2;
		b>>=1;
	}
	cout<<endl;
}

template<typename U, template <typename... Args> class Container,typename... Types>
U &operator<<(U &os, const Container<Types...> &x) {
	os<<"{";
	for(const auto &e:x)os<<" "<<e<<" ";
	os<<"}";
	return os;
}
//}}}

vector<int> generate(const vector<int> &a){
	vector<int> ret;
	int base = 1;
	REP(i,a.size()){
		REP(j,a[i])ret.push_back(base+j+1);
		ret.push_back(base);
		base+=a[i]+1;
	}
	return ret;
}

void solve(Int n, vector<Int> v, vector<Int> w){
//	assert(false);
	if(n==2){
		cout<<1<<" "<<2<<endl;
		return;
	}
	vector<bool> d(n,false);
	Graph g(n);
	REP(i,v.size()){
		addBiEdge(g,{v[i],w[i]});
	}
	int dsum = 0;
	REP(u,n){
		if(g[u].size()==1){
			d[u] = true;
			dsum++;
		}
	}
	vector<vector<int> > q;
	if(dsum==n-1){
		vector<int> s = {0,(int)n-2};
		q.push_back(s);
		if(s.back()>0){
			s.back()--;
			s.push_back(0);
			q.push_back(s);
		}
	}else{
		Graph h(n);
		REP(i,v.size()){
			if(!d[v[i]] and !d[w[i]]){
				addBiEdge(h,{v[i],w[i]});
			}
		}
		vector<int> deg_h_one;
		REP(u,n){
			if(h[u].size()==1){
				deg_h_one.push_back(u);
			}
		}
		if(deg_h_one.size()>=3/* or deg_h_one.size()==0*/){
			fout<<-1<<endl;
			return;
		}
		assert(deg_h_one.size()>0);
		vector<int> a;
		int prev = deg_h_one[0], u = h[prev][0].dst;
		a.push_back(prev);
		while(1){
			a.push_back(u);
			if(h[u].size()==1)break;
			if(h[u].size()>=3){
				fout<<-1<<endl;
				return;
			}
			int next_u = h[u][0].dst;
			if(next_u==prev)next_u = h[u][1].dst;
			prev = u;
			u = next_u;
		}
		REP(ct,2){
			vector<int> s = {0};
			REP(i,a.size()){
				if(i<(int)a.size()-1)s.push_back(g[a[i]].size()-2);
				else s.push_back(g[a[i]].size()-1);
			}
			q.push_back(s);
			if(s.back()>0){
				s.back()--;
				s.push_back(0);
				q.push_back(s);
			}
			reverse(ALL(a));
		}
	}
	vector<int> ans(n,n);
	for(auto &p:q){
		auto pp = generate(p);
		if(pp<ans)ans=pp;
	}
	REP(i,ans.size())fout<<ans[i]<<" ";
	fout<<endl;
}

//{{{ main function
int main(){	
	Int n;
	fin >> n;
	vector<Int> v((n-1)-1+1);
	vector<Int> w((n-1)-1+1);
	for(int i = 0 ; i <= (n-1)-1 ; i++){
		fin >> v[i];
		fin >> w[i];
		v[i]--;w[i]--;
	}
	solve(n, v, w);
	return 0;
}
//}}}