#include <bits/stdc++.h>
#define err(args...) {}
#ifdef DEBUG
#include "_debug.cpp"
#endif
using namespace std;
using ll = long long;
using ld = long double;
template <typename T> using lim = numeric_limits<T>;
template <typename T> istream& operator>>(istream& is, vector<T>& a) { for(T& x : a) { is >> x; } return is; }
template <bool Directed, typename TEdge, bool Index> struct graph {
    using EType = TEdge;
    vector<TEdge> edges;
    vector<vector<int>> adj;
    graph(int n) : adj(n + Index) {}
    graph(int n, int m) : graph(n) { edges.reserve(m << not Directed); }
    TEdge& operator()(int e) { return edges[e]; }
    vector<int>& operator[](int u) { return adj[u]; }
    int size() { return adj.size() - Index; }
    void add_edge(const TEdge& e) {
        adj[e.u].push_back(edges.size());
        edges.push_back(e);
        if(not Directed) {
            adj[e.v].push_back(edges.size());
            edges.push_back(e.reverse());
        }
    }
};
struct edge {
    int u, v;
    edge reverse() const { return {v, u}; }
    friend ostream& operator<<(ostream& os, const edge& e) {
        return os << "(" << e.u << ", " << e.v << ")";
    }
};
vector<int> get_innerness(int n, graph<0, edge, 1>& g) {
    vector<int> p(n + 1), degree(n + 1);
    queue<int> q;
    for(int u = 1; u <= n; u++) {
        if((degree[u] = g[u].size()) == 1) {
            q.push(u);
        }
    }
    while(not q.empty()) {
        int u = q.front();
        q.pop();
        for(int e : g[u]) {
            if(--degree[g(e).v] == 1) {
                p[g(e).v] = p[u] + 1;
                q.push(g(e).v);
            }
        }
    }
    return p;
}
bool valid(int n, graph<0, edge, 1>& g, vector<int>& innerness) {
    bool p = true;
    for(int u = 1; u <= n; u++) {
        if(innerness[u]) {
            int inner_neighbors = 0;
            for(int e : g[u]) {
                inner_neighbors += bool(innerness[g(e).v]);
            }
            p &= inner_neighbors <= 2;
        }
    }
    return p;
}
vector<int> make_rooted_p(int n, graph<0, edge, 1>& g, vector<int>& innerness, int root) {
    vector<int> p, index(n + 1);
    int id = 1;
    function<void(int, int)> dfs = [&](int u, int from) {
        sort(g[u].begin(), g[u].end(), [&](int e1, int e2) {
            return innerness[g(e1).v] < innerness[g(e2).v];
        });
        for(int e : g[u]) {
            if(g(e).v != from) {
                p.push_back(index[g(e).v] = id++);
            }
        }
        p.push_back(index[u]);
        swap(p[p.size() - 2], p[p.size() - 1]);
        for(int e : g[u]) {
            if(g(e).v != from and innerness[g(e).v]) {
                p.pop_back();
                dfs(g(e).v, u);
            }
        }
    };
    index[root] = id++;
    dfs(root, 0);
    return p;
}
vector<int> make_p(int n, graph<0, edge, 1>& g, vector<int>& innerness, int u) {
    for(int e : g[u]) {
        if(not innerness[g(e).v]) {
            return make_rooted_p(n, g, innerness, g(e).v);
        }
    }
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin >> n;
    if(n == 2) {
        cout << "1 2" << endl;
    } else {
        graph<0, edge, 1> g(n, n - 1);
        for(int i = 1; i < n; i++) {
            int u, v;
            cin >> u >> v;
            g.add_edge({u, v});
        }
        auto innerness = get_innerness(n, g);
        if(valid(n, g, innerness)) {
            vector<int> p(n);
            iota(p.begin(), p.end(), 1);
            reverse(p.begin(), p.end());
            for(int u = 1; u <= n; u++) {
                if(innerness[u] == 1) {
                    p = min(p, make_p(n, g, innerness, u));
                }
            }
            for(int u = 0; u < n; u++) {
                if(u) cout << " ";
                cout << p[u];
            }
            cout << endl;
        } else {
            cout << -1 << endl;
        }
    }
    return 0;
}


Measured memory_bytes: 20344