Problem: We had a really tough time generating tests for problem D. In order to prepare strong tests, we had to solve the following problem.

Given an undirected labeled tree consisting of n vertices, find a set of segments such that:

  1. both endpoints of each segment are integers from 1 to 2n, and each integer from 1 to 2n should appear as an endpoint of exactly one segment; 
  2. all segments are non-degenerate; 
  3. for each pair (i, j) such that i ≠ j, i ∈ [1, n] and j ∈ [1, n], the vertices i and j are connected with an edge if and only if the segments i and j intersect, but neither segment i is fully contained in segment j, nor segment j is fully contained in segment i. 



Can you solve this problem too?

Input

The first line contains one integer n (1 ≤ n ≤ 5 ⋅ 10^5) — the number of vertices in the tree.

Then n - 1 lines follow, each containing two integers x_i and y_i (1 ≤ x_i, y_i ≤ n, x_i ≠ y_i) denoting the endpoints of the i-th edge.

It is guaranteed that the given graph is a tree.

Output

Print n pairs of integers, the i-th pair should contain two integers l_i and r_i (1 ≤ l_i < r_i ≤ 2n) — the endpoints of the i-th segment. All 2n integers you print should be unique.

It is guaranteed that the answer always exists.

Examples

Input


6
1 2
1 3
3 4
3 5
2 6


Output


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


Input


1


Output


1 2

Solution (in JAVA):

Solution:
//package cf1;

import java.io.*;
import java.util.*;
 
public class utkarsh {
    
    BufferedReader br;
    PrintWriter out;
    
    long mod = (long) (1e9 + 7), inf = (long) (3e18);
    
    class pair {
        int L, R;
        pair(int l, int r) {
            L = l;  R = r;
        }
    }
    
    ArrayList <Integer> a[];
    pair seg[];
    int R;
    
    void dfs(int s, int pt) {
        int l = seg[s].R - 1;
        for(int x : a[s]) {
            if(x == pt) continue;
            R += a[x].size();
            seg[x].L = l--;
            seg[x].R = R;
            dfs(x, s);
        }
    }
    
    void solve() {
        int n = ni();
        a = new ArrayList[n];
        for(int i = 0; i < n; i++)  a[i] = new ArrayList<>();
        for(int i = 0; i < n-1; i++) {
            int u = ni() - 1, v = ni() - 1;
            a[u].add(v);
            a[v].add(u);
        }
        seg = new pair[n];
        for(int i = 0; i < n; i++)  seg[i] = new pair(-1, -1);
        seg[0].L = 1;   seg[0].R = a[0].size() + 2;
        R = seg[0].R;
        dfs(0, -1);
        for(int i = 0; i < n; i++)  out.println(seg[i].L +" "+ seg[i].R);
    }
    
    long mp(long b, long e) {
        long r = 1;
        while(e > 0) {
            if( (e&1) == 1 )    r = (r * b) % mod;
            b = (b * b) % mod;
            e >>= 1;
        }
        return r;
    }
    
    // -------- I/O Template -------------
    
    char nc() {
        return ns().charAt(0);
    }
    
    String nLine() {
        try {
            return br.readLine();
        } catch(IOException e) {
            return "-1";
        }
    }
    
    double nd() {
        return Double.parseDouble(ns());
    }
    
    long nl() {
        return Long.parseLong(ns());
    }
    
    int ni() {
        return Integer.parseInt(ns());
    }
    
    StringTokenizer ip;
    
    String ns() {
        if(ip == null || !ip.hasMoreTokens()) {
            try {
                ip = new StringTokenizer(br.readLine());
            } catch(IOException e) {
                throw new InputMismatchException();
            }
        }
        return ip.nextToken();
    }
    
    void run() {
        br = new BufferedReader(new InputStreamReader(System.in));
        out = new PrintWriter(System.out);
        solve();
        out.flush();
    }
    
    public static void main(String[] args) {
        new utkarsh().run();
    }
}