import java.io.*;
import java.util.*;

public class tr1 {
	static PrintWriter out;
	static StringBuilder sb;
	static int inf = (int) 1e9;
	static long mod = (long) 1e9 + 7;
	static int[] si;
	static ArrayList<Integer> primes;
	static HashSet<Integer> pr;
	static int n, k, m;
	static int[] in;
	static HashMap<Integer, Integer> factors;
	static HashSet<Integer> f;
	static int[] fac, a, b;
	static int[] l, r;
	static int[][] memo;
	static int[] numc;
	static ArrayList<Integer>[] ad;
	static HashMap<Integer, Integer> hm;
	static pair[] ed;
	static TreeSet<Integer>[] np;
	static TreeMap<pair, Integer> tm;
	static int[] le,re;
	static char[] h;
	static pair[] mm;
	static boolean[] vis;
    static int y;
	public static void main(String[] args) throws Exception {
		Scanner sc = new Scanner(System.in);
		out = new PrintWriter(System.out);
	    int n=sc.nextInt();
	    ad=new ArrayList[n];
	    for(int i=0;i<n;i++)
	    	ad[i]=new ArrayList<>();
	   // int m=sc.nextInt();
	    for(int i=0;i<n-1;i++) {
	    	int a=sc.nextInt()-1;
	    	int b=sc.nextInt()-1;
	    	ad[a].add(b);
	    	ad[b].add(a);
	    }
	    re=new int [n];
	    le=new int [n];
	    y=1;
	    le[0]=y;
	    dfs(0,-1);
	    for(int i=0;i<n;i++)
	    	out.println(le[i]+" "+re[i]);
		out.flush();
	}
	static void dfs(int u,int p) {
		for(int v:ad[u]) {
			if(v!=p) {
				le[v]=++y;
			}
		}
		re[u]=++y;
		for(int v=ad[u].size()-1;v>=0;v--) {
			if(ad[u].get(v)!=p) {
		      dfs(ad[u].get(v),u);
			}
		}

	}
	static class pair implements Comparable<pair> {
		int x;
		int y;
    //    int z;
 		pair(int f, int t) {
			x = f;
			y = t;
		//	z=u;
			// num = n;
		}

		public String toString() {
			return x + " " + y;
		}

		@Override
		public int compareTo(pair o) {
			if(x==o.x)
				return y-o.y;
			return o.x-x;
		}
	}

	static class pair1 implements Comparable<pair1> {
		int x;
		int y;
        int z;
 		pair1(int f, int t,int u) {
			x = f;
			y = t;
			z=u;
			// num = n;
		}

		public String toString() {
			return x + " " + y;
		}

		@Override
		public int compareTo(pair1 o) {
			if(x==o.x)
				return y-o.y;
			return x-o.x;
		}
	}

	static public class FenwickTree { // one-based DS

		int n;
		int[] ft;

		FenwickTree(int size) {
			n = size;
			ft = new int[n + 1];
		//	for(int i=1;i<=n;i++)
	//			ft[i]=i;
		}

		int rsq(int b) // O(log n)
		{
			int sum = 0;
			while (b > 0) {
				sum += ft[b];
				b -= b & -b;
			} // min?
			return sum;
		}

		int rsq(int a, int b) {
			return rsq(b) - rsq(a - 1);
		}

		void point_update(int k, int val) // O(log n), update = increment
		{
			while (k <= n) {
			//	System.out.println(k+" "+val);
				ft[k] += val;
				k += k & -k;
			} // min?
		}

		int point_query(int idx) // c * O(log n), c < 1
		{
			int sum = ft[idx];
			if (idx > 0) {
				int z = idx ^ (idx & -idx);
				--idx;
				while (idx != z) {
				//	System.out.println("oo");
					sum -= ft[idx];
					idx ^= idx & -idx;
				}
			}
			return sum;
		}

		void scale(int c) {
			for (int i = 1; i <= n; ++i)
				ft[i] *= c;
		}

		int findIndex(int cumFreq) {
			int msk = n;
			while ((msk & (msk - 1)) != 0)
				msk ^= msk & -msk; // msk will contain the MSB of n

			int idx = 0;
			while (msk != 0) {
				int tIdx = idx + msk;
				if (tIdx <= n && cumFreq >= ft[tIdx]) {
					idx = tIdx;
					cumFreq -= ft[tIdx];
				}
				msk >>= 1;
			}
			if (cumFreq != 0)
				return -1;
			return idx;
		}
	}

	static public class SegmentTree { // 1-based DS, OOP

		int N; // the number of elements in the array as a power of 2 (i.e. after padding)
		long[] array, sTree, lazy;

		SegmentTree(long[] in) {
			array = in;
			N = in.length - 1;
			sTree = new long[N << 1]; // no. of nodes = 2*N - 1, we add one to cross out index zero
			lazy = new long[N << 1];
			build(1, 1, N);
		}

		void build(int node, int b, int e) // O(n)
		{
			if (b == e)
				sTree[node] = array[b];
			else {
				int mid = b + e >> 1;
				build(node << 1, b, mid);
				build(node << 1 | 1, mid + 1, e);
				sTree[node] = sTree[node << 1] + sTree[node << 1 | 1];
			}
		}

		void update_point(int index, int val) // O(log n)
		{
			index += N - 1;
			sTree[index] += val;
			while (index > 1) {
				index >>= 1;
				sTree[index] = sTree[index << 1] + sTree[index << 1 | 1];
			}
		}

		void update_range(int i, int j, long val) // O(log n)
		{
			update_range(1, 1, N, i, j, val);
		}

		void update_range(int node, int b, int e, int i, int j, long val) {
			if (i > e || j < b)
				return;
			if (b >= i && e <= j) {
				sTree[node] += (e - b + 1) * val;
				lazy[node] += val;
			} else {
				int mid = b + e >> 1;
				propagate(node, b, mid, e);
				update_range(node << 1, b, mid, i, j, val);
				update_range(node << 1 | 1, mid + 1, e, i, j, val);
				sTree[node] = sTree[node << 1] + sTree[node << 1 | 1];
			}

		}

		void propagate(int node, int b, int mid, int e) {
			lazy[node << 1] += lazy[node];
			lazy[node << 1 | 1] += lazy[node];
			sTree[node << 1] += (mid - b + 1) * lazy[node];
			sTree[node << 1 | 1] += (e - mid) * lazy[node];
			lazy[node] = 0;
		}

		long query(int i, int j) {
			return query(1, 1, N, i, j);
		}

		long query(int node, int b, int e, int i, int j) // O(log n)
		{
			if (i > e || j < b)
				return 0;
			if (b >= i && e <= j)
				return sTree[node];
			int mid = b + e >> 1;
			propagate(node, b, mid, e);
			long q1 = query(node << 1, b, mid, i, j);
			long q2 = query(node << 1 | 1, mid + 1, e, i, j);
			return q1 + q2;

		}

	}

	static long gcd(long a, long b) {

		if (b == 0) {
			return a;
		}
		return gcd(b, a % b);
	}

	public int[] merge(int[] d, int st, int e) {
		if (st > e)
			return null;
		if (e == st) {
			int[] ans = { d[e] };
			return ans;
		}
		int mid = (st + e) / 2;
		int[] ans = new int[e - st + 1];
		int[] ll = merge(d, st, mid);
		int[] rr = merge(d, mid + 1, e);
		if (ll == null)
			return rr;
		if (rr == null)
			return ll;
		int iver = 0;
		int idxl = 0;
		int idxr = 0;
		for (int i = st; i <= e; i++) {
			if (ll[idxl] < rr[idxr]) {

			}
		}
		return ans;
	}

	public static class pair2 implements Comparable<pair2> {
		int a;
		int idx;

		pair2(int a, int i) {
			this.a = a;
			idx = i;
		}

		public String toString() {
			return a + " " + idx;
		}

		@Override
		public int compareTo(pair2 o) {
			// TODO Auto-generated method stub
			return idx - o.idx;
		}
	}

	static long inver(long x) {
		int a = (int) x;
		long e = (mod - 2);
		long res = 1;
		while (e > 0) {
			if ((e & 1) == 1) {
				// System.out.println(res*a);
				res = (int) ((1l * res * a) % mod);
			}
			a = (int) ((1l * a * a) % mod);
			e >>= 1;
		}
		// out.println(res+" "+x);
		return res % mod;
	}

	static int atMostSum(int arr[], int n, int k) {
		int sum = 0;
		int cnt = 0, maxcnt = 0;

		for (int i = 0; i < n; i++) {

			// If adding current element doesn't
			// cross limit add it to current window
			if ((sum + arr[i]) <= k) {
				sum += arr[i];
				cnt++;
			}

			// Else, remove first element of current
			// window and add the current element
			else if (sum != 0) {
				sum = sum - arr[i - cnt] + arr[i];
			}

			// keep track of max length.
			maxcnt = Math.max(cnt, maxcnt);
		}
		return maxcnt;
	}

	public static int[] longestSubarray(int[] inp) {
		// array containing prefix sums up to a certain index i
		int[] p = new int[inp.length];
		p[0] = inp[0];
		for (int i = 1; i < inp.length; i++) {
			p[i] = p[i - 1] + inp[i];
		}

		// array Q from the description below
		int[] q = new int[inp.length];
		q[inp.length - 1] = p[inp.length - 1];
		for (int i = inp.length - 2; i >= 0; i--) {
			q[i] = Math.max(q[i + 1], p[i]);
		}
		int a = 0;
		int b = 0;
		int maxLen = 0;
		int curr;
		int[] res = new int[] { -1, -1 };
		while (b < inp.length) {
			curr = a > 0 ? q[b] - p[a - 1] : q[b];
			if (curr >= 0) {
				if (b - a > maxLen) {
					maxLen = b - a;
					res = new int[] { a, b };
				}
				b++;
			} else {
				a++;
			}
		}
		return res;
	}

	static void factor(int n) {
		if (si[n] == n) {
			f.add(n);
			return;
		}
		f.add(si[n]);
		factor(n / si[n]);
	}

	static void seive() {
		si = new int[100001];
		primes = new ArrayList<>();
		int N = 100001;
		si[1] = 1;
		for (int i = 2; i < N; i++) {
			if (si[i] == 0) {
				si[i] = i;
				primes.add(i);
			}
			for (int j = 0; j < primes.size() && primes.get(j) <= si[i] && (i * primes.get(j)) < N; j++)
				si[primes.get(j) * i] = primes.get(j);

		}
	}

	static class unionfind {
		int[] p;
		int[] size;
           int jum;
		unionfind(int n) {
			p = new int[n];
			size = new int[n];

			for (int i = 0; i < n; i++) {
				p[i] = i;
			}
			jum=n;
			Arrays.fill(size, 1);
		}

		int findSet(int v) {
			if (v == p[v])
				return v;
			return p[v] = findSet(p[v]);
		}

		boolean sameSet(int a, int b) {
			a = findSet(a);
			b = findSet(b);
			if (a == b)
				return true;
			return false;
		}

		int max() {
			int max = 0;
			for (int i = 0; i < size.length; i++)
				if (size[i] > max)
					max = size[i];
			return max;
		}

		void combine(int a, int b) {
			a = findSet(a);
			b = findSet(b);
			if (a == b)
				return;
			jum--;
			if (size[a] > size[b]) {
				p[b] = a;
				size[a] += size[b];

			} else {
				p[a] = b;
				size[b] += size[a];
			}
		}
	}

	static class Scanner {
		StringTokenizer st;
		BufferedReader br;

		public Scanner(InputStream system) {
			br = new BufferedReader(new InputStreamReader(system));
		}

		public Scanner(String file) throws Exception {
			br = new BufferedReader(new FileReader(file));
		}

		public String next() throws IOException {
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		public String nextLine() throws IOException {
			return br.readLine();
		}

		public int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		public double nextDouble() throws IOException {
			return Double.parseDouble(next());
		}

		public char nextChar() throws IOException {
			return next().charAt(0);
		}

		public Long nextLong() throws IOException {
			return Long.parseLong(next());
		}

		public boolean ready() throws IOException {
			return br.ready();
		}

		public void waitForInput() throws InterruptedException {
			Thread.sleep(3000);
		}
	}
}


import java.io.*;
import java.util.*;

public class tr1 {
	static PrintWriter out;
	static StringBuilder sb;
	static int inf = (int) 1e9;
	static long mod = (long) 1e9 + 7;
	static int[] si;
	static ArrayList<Integer> primes;
	static HashSet<Integer> pr;
	static int n, k, m;
	static int[] in;
	static HashMap<Integer, Integer> factors;
	static HashSet<Integer> f;
	static int[] fac, a, b;
	static int[] l, r;
	static int[][] memo;
	static int[] numc;
	static ArrayList<Integer>[] ad;
	static HashMap<Integer, Integer> hm;
	static pair[] ed;
	static TreeSet<Integer>[] np;
	static TreeMap<pair, Integer> tm;
	static int[] le,re;
	static char[] h;
	static pair[] mm;
	static boolean[] vis;
    static int y;
	public static void main(String[] args) throws Exception {
		Scanner sc = new Scanner(System.in);
		out = new PrintWriter(System.out);
	    int n=sc.nextInt();
	    ad=new ArrayList[n];
	    for(int i=0;i<n;i++)
	    	ad[i]=new ArrayList<>();
	   // int m=sc.nextInt();
	    for(int i=0;i<n-1;i++) {
	    	int a=sc.nextInt()-1;
	    	int b=sc.nextInt()-1;
	    	ad[a].add(b);
	    	ad[b].add(a);
	    }
	    re=new int [n];
	    le=new int [n];
	    y=1;
	    le[0]=y;
	    dfs(0,-1);
	    for(int i=0;i<n;i++)
	    	out.println(le[i]+" "+re[i]);
		out.flush();
	}
	static void dfs(int u,int p) {
		for(int v:ad[u]) {
			if(v!=p) {
				le[v]=++y;
			}
		}
		re[u]=++y;
		for(int v:ad[u]) {
			if(v!=p) {
		      dfs(v,u);
			}
		}

	}
	static class pair implements Comparable<pair> {
		int x;
		int y;
    //    int z;
 		pair(int f, int t) {
			x = f;
			y = t;
		//	z=u;
			// num = n;
		}

		public String toString() {
			return x + " " + y;
		}

		@Override
		public int compareTo(pair o) {
			if(x==o.x)
				return y-o.y;
			return o.x-x;
		}
	}

	static class pair1 implements Comparable<pair1> {
		int x;
		int y;
        int z;
 		pair1(int f, int t,int u) {
			x = f;
			y = t;
			z=u;
			// num = n;
		}

		public String toString() {
			return x + " " + y;
		}

		@Override
		public int compareTo(pair1 o) {
			if(x==o.x)
				return y-o.y;
			return x-o.x;
		}
	}

	static public class FenwickTree { // one-based DS

		int n;
		int[] ft;

		FenwickTree(int size) {
			n = size;
			ft = new int[n + 1];
		//	for(int i=1;i<=n;i++)
	//			ft[i]=i;
		}

		int rsq(int b) // O(log n)
		{
			int sum = 0;
			while (b > 0) {
				sum += ft[b];
				b -= b & -b;
			} // min?
			return sum;
		}

		int rsq(int a, int b) {
			return rsq(b) - rsq(a - 1);
		}

		void point_update(int k, int val) // O(log n), update = increment
		{
			while (k <= n) {
			//	System.out.println(k+" "+val);
				ft[k] += val;
				k += k & -k;
			} // min?
		}

		int point_query(int idx) // c * O(log n), c < 1
		{
			int sum = ft[idx];
			if (idx > 0) {
				int z = idx ^ (idx & -idx);
				--idx;
				while (idx != z) {
				//	System.out.println("oo");
					sum -= ft[idx];
					idx ^= idx & -idx;
				}
			}
			return sum;
		}

		void scale(int c) {
			for (int i = 1; i <= n; ++i)
				ft[i] *= c;
		}

		int findIndex(int cumFreq) {
			int msk = n;
			while ((msk & (msk - 1)) != 0)
				msk ^= msk & -msk; // msk will contain the MSB of n

			int idx = 0;
			while (msk != 0) {
				int tIdx = idx + msk;
				if (tIdx <= n && cumFreq >= ft[tIdx]) {
					idx = tIdx;
					cumFreq -= ft[tIdx];
				}
				msk >>= 1;
			}
			if (cumFreq != 0)
				return -1;
			return idx;
		}
	}

	static public class SegmentTree { // 1-based DS, OOP

		int N; // the number of elements in the array as a power of 2 (i.e. after padding)
		long[] array, sTree, lazy;

		SegmentTree(long[] in) {
			array = in;
			N = in.length - 1;
			sTree = new long[N << 1]; // no. of nodes = 2*N - 1, we add one to cross out index zero
			lazy = new long[N << 1];
			build(1, 1, N);
		}

		void build(int node, int b, int e) // O(n)
		{
			if (b == e)
				sTree[node] = array[b];
			else {
				int mid = b + e >> 1;
				build(node << 1, b, mid);
				build(node << 1 | 1, mid + 1, e);
				sTree[node] = sTree[node << 1] + sTree[node << 1 | 1];
			}
		}

		void update_point(int index, int val) // O(log n)
		{
			index += N - 1;
			sTree[index] += val;
			while (index > 1) {
				index >>= 1;
				sTree[index] = sTree[index << 1] + sTree[index << 1 | 1];
			}
		}

		void update_range(int i, int j, long val) // O(log n)
		{
			update_range(1, 1, N, i, j, val);
		}

		void update_range(int node, int b, int e, int i, int j, long val) {
			if (i > e || j < b)
				return;
			if (b >= i && e <= j) {
				sTree[node] += (e - b + 1) * val;
				lazy[node] += val;
			} else {
				int mid = b + e >> 1;
				propagate(node, b, mid, e);
				update_range(node << 1, b, mid, i, j, val);
				update_range(node << 1 | 1, mid + 1, e, i, j, val);
				sTree[node] = sTree[node << 1] + sTree[node << 1 | 1];
			}

		}

		void propagate(int node, int b, int mid, int e) {
			lazy[node << 1] += lazy[node];
			lazy[node << 1 | 1] += lazy[node];
			sTree[node << 1] += (mid - b + 1) * lazy[node];
			sTree[node << 1 | 1] += (e - mid) * lazy[node];
			lazy[node] = 0;
		}

		long query(int i, int j) {
			return query(1, 1, N, i, j);
		}

		long query(int node, int b, int e, int i, int j) // O(log n)
		{
			if (i > e || j < b)
				return 0;
			if (b >= i && e <= j)
				return sTree[node];
			int mid = b + e >> 1;
			propagate(node, b, mid, e);
			long q1 = query(node << 1, b, mid, i, j);
			long q2 = query(node << 1 | 1, mid + 1, e, i, j);
			return q1 + q2;

		}

	}

	static long gcd(long a, long b) {

		if (b == 0) {
			return a;
		}
		return gcd(b, a % b);
	}

	public int[] merge(int[] d, int st, int e) {
		if (st > e)
			return null;
		if (e == st) {
			int[] ans = { d[e] };
			return ans;
		}
		int mid = (st + e) / 2;
		int[] ans = new int[e - st + 1];
		int[] ll = merge(d, st, mid);
		int[] rr = merge(d, mid + 1, e);
		if (ll == null)
			return rr;
		if (rr == null)
			return ll;
		int iver = 0;
		int idxl = 0;
		int idxr = 0;
		for (int i = st; i <= e; i++) {
			if (ll[idxl] < rr[idxr]) {

			}
		}
		return ans;
	}

	public static class pair2 implements Comparable<pair2> {
		int a;
		int idx;

		pair2(int a, int i) {
			this.a = a;
			idx = i;
		}

		public String toString() {
			return a + " " + idx;
		}

		@Override
		public int compareTo(pair2 o) {
			// TODO Auto-generated method stub
			return idx - o.idx;
		}
	}

	static long inver(long x) {
		int a = (int) x;
		long e = (mod - 2);
		long res = 1;
		while (e > 0) {
			if ((e & 1) == 1) {
				// System.out.println(res*a);
				res = (int) ((1l * res * a) % mod);
			}
			a = (int) ((1l * a * a) % mod);
			e >>= 1;
		}
		// out.println(res+" "+x);
		return res % mod;
	}

	static int atMostSum(int arr[], int n, int k) {
		int sum = 0;
		int cnt = 0, maxcnt = 0;

		for (int i = 0; i < n; i++) {

			// If adding current element doesn't
			// cross limit add it to current window
			if ((sum + arr[i]) <= k) {
				sum += arr[i];
				cnt++;
			}

			// Else, remove first element of current
			// window and add the current element
			else if (sum != 0) {
				sum = sum - arr[i - cnt] + arr[i];
			}

			// keep track of max length.
			maxcnt = Math.max(cnt, maxcnt);
		}
		return maxcnt;
	}

	public static int[] longestSubarray(int[] inp) {
		// array containing prefix sums up to a certain index i
		int[] p = new int[inp.length];
		p[0] = inp[0];
		for (int i = 1; i < inp.length; i++) {
			p[i] = p[i - 1] + inp[i];
		}

		// array Q from the description below
		int[] q = new int[inp.length];
		q[inp.length - 1] = p[inp.length - 1];
		for (int i = inp.length - 2; i >= 0; i--) {
			q[i] = Math.max(q[i + 1], p[i]);
		}
		int a = 0;
		int b = 0;
		int maxLen = 0;
		int curr;
		int[] res = new int[] { -1, -1 };
		while (b < inp.length) {
			curr = a > 0 ? q[b] - p[a - 1] : q[b];
			if (curr >= 0) {
				if (b - a > maxLen) {
					maxLen = b - a;
					res = new int[] { a, b };
				}
				b++;
			} else {
				a++;
			}
		}
		return res;
	}

	static void factor(int n) {
		if (si[n] == n) {
			f.add(n);
			return;
		}
		f.add(si[n]);
		factor(n / si[n]);
	}

	static void seive() {
		si = new int[100001];
		primes = new ArrayList<>();
		int N = 100001;
		si[1] = 1;
		for (int i = 2; i < N; i++) {
			if (si[i] == 0) {
				si[i] = i;
				primes.add(i);
			}
			for (int j = 0; j < primes.size() && primes.get(j) <= si[i] && (i * primes.get(j)) < N; j++)
				si[primes.get(j) * i] = primes.get(j);

		}
	}

	static class unionfind {
		int[] p;
		int[] size;
           int jum;
		unionfind(int n) {
			p = new int[n];
			size = new int[n];

			for (int i = 0; i < n; i++) {
				p[i] = i;
			}
			jum=n;
			Arrays.fill(size, 1);
		}

		int findSet(int v) {
			if (v == p[v])
				return v;
			return p[v] = findSet(p[v]);
		}

		boolean sameSet(int a, int b) {
			a = findSet(a);
			b = findSet(b);
			if (a == b)
				return true;
			return false;
		}

		int max() {
			int max = 0;
			for (int i = 0; i < size.length; i++)
				if (size[i] > max)
					max = size[i];
			return max;
		}

		void combine(int a, int b) {
			a = findSet(a);
			b = findSet(b);
			if (a == b)
				return;
			jum--;
			if (size[a] > size[b]) {
				p[b] = a;
				size[a] += size[b];

			} else {
				p[a] = b;
				size[b] += size[a];
			}
		}
	}

	static class Scanner {
		StringTokenizer st;
		BufferedReader br;

		public Scanner(InputStream system) {
			br = new BufferedReader(new InputStreamReader(system));
		}

		public Scanner(String file) throws Exception {
			br = new BufferedReader(new FileReader(file));
		}

		public String next() throws IOException {
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		public String nextLine() throws IOException {
			return br.readLine();
		}

		public int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		public double nextDouble() throws IOException {
			return Double.parseDouble(next());
		}

		public char nextChar() throws IOException {
			return next().charAt(0);
		}

		public Long nextLong() throws IOException {
			return Long.parseLong(next());
		}

		public boolean ready() throws IOException {
			return br.ready();
		}

		public void waitForInput() throws InterruptedException {
			Thread.sleep(3000);
		}
	}
}


//package com.company;

import java.io.*;
import java.util.*;

public class Main {
    public static class Task {
        class DJS {
            int[] a;
            public DJS(int n) {
                a = new int[n];
                Arrays.fill(a, -1);
            }
            int find (int x) {
                if (a[x] < 0) return x;
                return a[x] = find(a[x]);
            }
            boolean union(int x, int y) {
                int rx = find(x), ry = find(y);
                if (rx== ry) return false;
                a[rx] = ry;
                return true;
            }
        }
        int glob = 0;
        List<Integer>[] edges;
        int[] start;
        int[] end;
        void dfs(int u, int p) {
            for (int v: edges[u]) if (v != p) {
                end[v] = glob--;
            }
            start[u] = glob--;
            for (int i = 0; i < edges[u].size(); i++) {
                int v = edges[u].get(edges[u].size() - 1- i);
                if (v == p) continue;
                dfs(v, u);
            }
        }

        public void solve(Scanner sc, PrintWriter pw) throws IOException {
            int n = sc.nextInt();
            edges = new List[n];
            for (int i = 0; i < n; i++) {
                edges[i] = new ArrayList<>();
            }
            for (int i = 0; i < n - 1; i++) {
                int a = sc.nextInt() - 1;
                int b = sc.nextInt() - 1;
                edges[a].add(b);
                edges[b].add(a);
            }
            glob = 2 * n;
            start = new int[n];
            end = new int[n];
            end[0] = glob--;

            dfs(0, -1);
            for (int i = 0; i < n;i ++) {
                pw.println(start[i] + " " + end[i]);
            }
        }

    }

    static long TIME_START, TIME_END;

    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
//        Scanner sc = new Scanner(new FileInputStream("input_line"));
        PrintWriter pw = new PrintWriter(new BufferedOutputStream(System.out));
//        PrintWriter pw = new PrintWriter(new FileOutputStream("input_line"));

        Runtime runtime = Runtime.getRuntime();
        long usedMemoryBefore = runtime.totalMemory() - runtime.freeMemory();
        TIME_START = System.currentTimeMillis();
        Task t = new Task();
        t.solve(sc, pw);
        TIME_END = System.currentTimeMillis();
        long usedMemoryAfter = runtime.totalMemory() - runtime.freeMemory();
        pw.close();
        System.err.println("Memory increased: " + (usedMemoryAfter - usedMemoryBefore) / 1000000);
        System.err.println("Time used: " + (TIME_END - TIME_START) + ".");
    }

    static class Scanner {
        StringTokenizer st;
        BufferedReader br;

        public Scanner(InputStream s) {
            br = new BufferedReader(new InputStreamReader(s));
        }

        public Scanner(FileReader s) throws FileNotFoundException {
            br = new BufferedReader(s);
        }

        public String next() throws IOException {
            while (st == null || !st.hasMoreTokens())
                st = new StringTokenizer(br.readLine());
            return st.nextToken();
        }

        public int nextInt() throws IOException {
            return Integer.parseInt(next());
        }

        public long nextLong() throws IOException {
            return Long.parseLong(next());
        }

        public String nextLine() throws IOException {
            return br.readLine();
        }

        public double nextDouble() throws IOException {
            return Double.parseDouble(next());
        }

        public boolean ready() throws IOException {
            return br.ready();
        }
    }
}


/**
 * BaZ :D
 */
import java.util.*;
import java.io.*;
import static java.lang.Math.*;

public class ACMIND
{
    static FastReader scan;
    static PrintWriter pw;
    static long MOD = 1_000_000_007 ;
    static long INF = 1_000_000_000_000_000_000L;
    static long inf = 2_000_000_000;
    public static void main(String[] args) {
        new Thread(null,null,"BaZ",1<<27)
        {
            public void run()
            {
                try
                {
                    solve();
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                    System.exit(1);
                }
            }
        }.start();
    }
    static int n,l[],r[],max;
    static ArrayList<Integer> adj[];
    static void solve() throws IOException
    {
        scan = new FastReader();
        pw = new PrintWriter(System.out,true);
        StringBuilder sb = new StringBuilder();
        n = ni();
        adj = new ArrayList[n+1];
        for(int i=1;i<=n;++i) {
            adj[i] = new ArrayList<>();
        }
        for(int i=1;i<n;++i) {
            int u = ni(), v = ni();
            adj[u].add(v);
            adj[v].add(u);
        }
        l = new int[n+1];
        r = new int[n+1];
        l[1] = 1;
        r[1] = 1+adj[1].size()+1;
        max = r[1];
        for(int i=0;i<adj[1].size(); ++i) {
            dfs(adj[1].get(i), 1, i);
        }
        for(int i=1;i<=n;++i) {
            pl(l[i]+" "+r[i]);
        }
        pw.flush();
        pw.close();
    }
    static void dfs(int v, int par, int pos) {
        l[v] = r[par] - (pos+1);
        r[v] = max + adj[v].size();
        max = r[v];
        int ptr = 0;
        for(int i=0;i<adj[v].size();++i) {
            if(adj[v].get(i) != par) {
                dfs(adj[v].get(i), v, ptr++);
            }
        }
    }
    static int ni() throws IOException
    {
        return scan.nextInt();
    }
    static long nl() throws IOException
    {
        return scan.nextLong();
    }
    static double nd() throws IOException
    {
        return scan.nextDouble();
    }
    static void pl()
    {
        pw.println();
    }
    static void p(Object o)
    {
        pw.print(o+" ");
    }
    static void pl(Object o)
    {
        pw.println(o);
    }
    static void psb(StringBuilder sb)
    {
        pw.print(sb);
    }
    static void pa(String arrayName, Object arr[])
    {
        pl(arrayName+" : ");
        for(Object o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, int arr[])
    {
        pl(arrayName+" : ");
        for(int o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, long arr[])
    {
        pl(arrayName+" : ");
        for(long o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, double arr[])
    {
        pl(arrayName+" : ");
        for(double o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, char arr[])
    {
        pl(arrayName+" : ");
        for(char o : arr)
            p(o);
        pl();
    }
    static void pa(String listName, List list)
    {
        pl(listName+" : ");
        for(Object o : list)
            p(o);
        pl();
    }
    static void pa(String arrayName, Object[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(Object o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, int[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(int o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, long[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(long o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, char[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(char o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, double[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(double o : arr[i])
                p(o);
            pl();
        }
    }
    static class FastReader {
        final private int BUFFER_SIZE = 1 << 16;
        private DataInputStream din;
        private byte[] buffer;
        private int bufferPointer, bytesRead;

        public FastReader() {
            din = new DataInputStream(System.in);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public FastReader(String file_name) throws IOException {
            din = new DataInputStream(new FileInputStream(file_name));
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public String readLine() throws IOException {
            byte[] buf = new byte[1000000];
            int cnt = 0, c;
            while ((c = read()) != -1) {
                if (c == '\n') break;
                buf[cnt++] = (byte) c;
            }
            return new String(buf, 0, cnt);
        }

        public int nextInt() throws IOException {
            int ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public long nextLong() throws IOException {
            long ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public double nextDouble() throws IOException {
            double ret = 0, div = 1;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (c == '.') while ((c = read()) >= '0' && c <= '9') ret += (c - '0') / (div *= 10);
            if (neg) return -ret;
            return ret;
        }

        private void fillBuffer() throws IOException {
            bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
            if (bytesRead == -1) buffer[0] = -1;
        }

        private byte read() throws IOException {
            if (bufferPointer == bytesRead) fillBuffer();
            return buffer[bufferPointer++];
        }

        public void close() throws IOException {
            if (din == null) return;
            din.close();
        }
    }
}


/**
 * BaZ :D
 */
import java.util.*;
import java.io.*;
import static java.lang.Math.*;

public class ACMIND
{
    static FastReader scan;
    static PrintWriter pw;
    static long MOD = 1_000_000_007 ;
    static long INF = 1_000_000_000_000_000_000L;
    static long inf = 2_000_000_000;
    public static void main(String[] args) {
        new Thread(null,null,"BaZ",1<<27)
        {
            public void run()
            {
                try
                {
                    solve();
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                    System.exit(1);
                }
            }
        }.start();
    }
    static int n,l[],r[],max;
    static ArrayList<Integer> adj[];
    static void solve() throws IOException
    {
        scan = new FastReader();
        pw = new PrintWriter(System.out,true);
        StringBuilder sb = new StringBuilder();
        n = ni();
        adj = new ArrayList[n+1];
        for(int i=1;i<=n;++i) {
            adj[i] = new ArrayList<>();
        }
        for(int i=1;i<n;++i) {
            int u = ni(), v = ni();
            adj[u].add(v);
            adj[v].add(u);
        }
        l = new int[n+1];
        r = new int[n+1];
        l[1] = 1;
        r[1] = 1+adj[1].size()+1;
        max = r[1];
        int idx = 0;
        for(int e : adj[1]) {
            dfs(e, 1, idx++);
        }
        for(int i=1;i<=n;++i) {
            sb.append(l[i]);
            sb.append(" ");
            sb.append(r[i]);
            sb.append("\n");
        }
        psb(sb);
        pw.flush();
        pw.close();
    }
    static void dfs(int v, int par, int pos) {
        l[v] = r[par] - (pos+1);
        r[v] = max + adj[v].size();
        max = r[v];
        int ptr = 0;
        for(int e : adj[v]) {
            if(e!=par) {
                dfs(e, v, ptr++);
            }
        }
    }
    static int ni() throws IOException
    {
        return scan.nextInt();
    }
    static long nl() throws IOException
    {
        return scan.nextLong();
    }
    static double nd() throws IOException
    {
        return scan.nextDouble();
    }
    static void pl()
    {
        pw.println();
    }
    static void p(Object o)
    {
        pw.print(o+" ");
    }
    static void pl(Object o)
    {
        pw.println(o);
    }
    static void psb(StringBuilder sb)
    {
        pw.print(sb);
    }
    static void pa(String arrayName, Object arr[])
    {
        pl(arrayName+" : ");
        for(Object o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, int arr[])
    {
        pl(arrayName+" : ");
        for(int o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, long arr[])
    {
        pl(arrayName+" : ");
        for(long o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, double arr[])
    {
        pl(arrayName+" : ");
        for(double o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, char arr[])
    {
        pl(arrayName+" : ");
        for(char o : arr)
            p(o);
        pl();
    }
    static void pa(String listName, List list)
    {
        pl(listName+" : ");
        for(Object o : list)
            p(o);
        pl();
    }
    static void pa(String arrayName, Object[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(Object o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, int[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(int o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, long[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(long o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, char[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(char o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, double[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(double o : arr[i])
                p(o);
            pl();
        }
    }
    static class FastReader {
        final private int BUFFER_SIZE = 1 << 16;
        private DataInputStream din;
        private byte[] buffer;
        private int bufferPointer, bytesRead;

        public FastReader() {
            din = new DataInputStream(System.in);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public FastReader(String file_name) throws IOException {
            din = new DataInputStream(new FileInputStream(file_name));
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public String readLine() throws IOException {
            byte[] buf = new byte[1000000];
            int cnt = 0, c;
            while ((c = read()) != -1) {
                if (c == '\n') break;
                buf[cnt++] = (byte) c;
            }
            return new String(buf, 0, cnt);
        }

        public int nextInt() throws IOException {
            int ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public long nextLong() throws IOException {
            long ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public double nextDouble() throws IOException {
            double ret = 0, div = 1;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (c == '.') while ((c = read()) >= '0' && c <= '9') ret += (c - '0') / (div *= 10);
            if (neg) return -ret;
            return ret;
        }

        private void fillBuffer() throws IOException {
            bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
            if (bytesRead == -1) buffer[0] = -1;
        }

        private byte read() throws IOException {
            if (bufferPointer == bytesRead) fillBuffer();
            return buffer[bufferPointer++];
        }

        public void close() throws IOException {
            if (din == null) return;
            din.close();
        }
    }
}


/**
 * BaZ :D
 */
import java.util.*;
import java.io.*;
import static java.lang.Math.*;

public class ACMIND
{
    static FastReader scan;
    static PrintWriter pw;
    static long MOD = 1_000_000_007 ;
    static long INF = 1_000_000_000_000_000_000L;
    static long inf = 2_000_000_000;
    public static void main(String[] args) {
        new Thread(null,null,"BaZ",1<<27)
        {
            public void run()
            {
                try
                {
                    solve();
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                    System.exit(1);
                }
            }
        }.start();
    }
    static int n,l[],r[],max;
    static ArrayList<Integer> adj[];
    static void solve() throws IOException
    {
        scan = new FastReader();
        pw = new PrintWriter(System.out,true);
        StringBuilder sb = new StringBuilder();
        n = ni();
        adj = new ArrayList[n+1];
        for(int i=1;i<=n;++i) {
            adj[i] = new ArrayList<>();
        }
        for(int i=1;i<n;++i) {
            int u = ni(), v = ni();
            adj[u].add(v);
            adj[v].add(u);
        }
        l = new int[n+1];
        r = new int[n+1];
        l[1] = 1;
        r[1] = 1+adj[1].size()+1;
        max = r[1];
        int idx = 0;
        for(int e : adj[1]) {
            dfs(e, 1, idx++);
        }
        for(int i=1;i<=n;++i) {
            pl(l[i]+" "+r[i]);
        }
        pw.flush();
        pw.close();
    }
    static void dfs(int v, int par, int pos) {
        l[v] = r[par] - (pos+1);
        r[v] = max + adj[v].size();
        max = r[v];
        int ptr = 0;
        for(int e : adj[v]) {
            if(e!=par) {
                dfs(e, v, ptr++);
            }
        }
    }
    static int ni() throws IOException
    {
        return scan.nextInt();
    }
    static long nl() throws IOException
    {
        return scan.nextLong();
    }
    static double nd() throws IOException
    {
        return scan.nextDouble();
    }
    static void pl()
    {
        pw.println();
    }
    static void p(Object o)
    {
        pw.print(o+" ");
    }
    static void pl(Object o)
    {
        pw.println(o);
    }
    static void psb(StringBuilder sb)
    {
        pw.print(sb);
    }
    static void pa(String arrayName, Object arr[])
    {
        pl(arrayName+" : ");
        for(Object o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, int arr[])
    {
        pl(arrayName+" : ");
        for(int o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, long arr[])
    {
        pl(arrayName+" : ");
        for(long o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, double arr[])
    {
        pl(arrayName+" : ");
        for(double o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, char arr[])
    {
        pl(arrayName+" : ");
        for(char o : arr)
            p(o);
        pl();
    }
    static void pa(String listName, List list)
    {
        pl(listName+" : ");
        for(Object o : list)
            p(o);
        pl();
    }
    static void pa(String arrayName, Object[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(Object o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, int[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(int o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, long[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(long o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, char[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(char o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, double[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(double o : arr[i])
                p(o);
            pl();
        }
    }
    static class FastReader {
        final private int BUFFER_SIZE = 1 << 16;
        private DataInputStream din;
        private byte[] buffer;
        private int bufferPointer, bytesRead;

        public FastReader() {
            din = new DataInputStream(System.in);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public FastReader(String file_name) throws IOException {
            din = new DataInputStream(new FileInputStream(file_name));
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public String readLine() throws IOException {
            byte[] buf = new byte[1000000];
            int cnt = 0, c;
            while ((c = read()) != -1) {
                if (c == '\n') break;
                buf[cnt++] = (byte) c;
            }
            return new String(buf, 0, cnt);
        }

        public int nextInt() throws IOException {
            int ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public long nextLong() throws IOException {
            long ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public double nextDouble() throws IOException {
            double ret = 0, div = 1;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (c == '.') while ((c = read()) >= '0' && c <= '9') ret += (c - '0') / (div *= 10);
            if (neg) return -ret;
            return ret;
        }

        private void fillBuffer() throws IOException {
            bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
            if (bytesRead == -1) buffer[0] = -1;
        }

        private byte read() throws IOException {
            if (bufferPointer == bytesRead) fillBuffer();
            return buffer[bufferPointer++];
        }

        public void close() throws IOException {
            if (din == null) return;
            din.close();
        }
    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.util.ArrayList;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author Sparsh Sanchorawala
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        ETestsForProblemD solver = new ETestsForProblemD();
        solver.solve(1, in, out);
        out.close();
    }

    static class ETestsForProblemD {
        ArrayList<Integer>[] adj;
        int[] resl;
        int[] resr;
        int[] sub;
        int[] child;

        void fillsub(int x, int p) {
            sub[x]++;
            for (int y : adj[x]) {
                if (y != p) {
                    child[x]++;
                    fillsub(y, x);
                    sub[x] += sub[y];
                }
            }
        }

        void recur(int x, int l, int m, int p) {
            resl[x] = l;
            resr[x] = m + child[x];
            int c = 1;
            int s = 0;
            for (int y : adj[x]) {
                if (y != p) {
                    recur(y, resr[x] - c, resr[x] - c + 2 * s + 2, x);
                    c++;
                    s += sub[y];
                }
            }
        }

        public void solve(int testNumber, InputReader s, PrintWriter w) {
            int n = s.nextInt();
            adj = new ArrayList[n];
            for (int i = 0; i < n; i++)
                adj[i] = new ArrayList<>();
            for (int i = 0; i < n - 1; i++) {
                int u = s.nextInt() - 1, v = s.nextInt() - 1;
                adj[u].add(v);
                adj[v].add(u);
            }
            child = new int[n];
            sub = new int[n];
            fillsub(0, -1);
            resl = new int[n];
            resr = new int[n];
            recur(0, 0, 1, -1);
            for (int i = 0; i < n; i++)
                w.println((resl[i] + 1) + " " + (resr[i] + 1));
        }

    }

    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private InputReader.SpaceCharFilter filter;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        public int read() {
            if (numChars == -1) {
                throw new InputMismatchException();
            }
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0) {
                    return -1;
                }
            }
            return buf[curChar++];
        }

        public int nextInt() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public boolean isSpaceChar(int c) {
            if (filter != null) {
                return filter.isSpaceChar(c);
            }
            return isWhitespace(c);
        }

        public static boolean isWhitespace(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);

        }

    }
}


import java.util.*;
import java.io.*;
public class TestD {

	static BufferedReader br;
	static StringTokenizer tokenizer;

	public static void main(String[] args) throws Exception {
		br = new BufferedReader(new InputStreamReader(System.in));
		int n = nextInt();
		ArrayList<Integer>[] adj = new ArrayList[n];
		for(int i = 0; i < n; i++)
			adj[i] = new ArrayList<Integer>();
		for(int i = 0; i < n - 1; i++) {
			int a = nextInt() - 1;
			int b = nextInt() - 1;
			adj[a].add(b);
			adj[b].add(a);
		}
		ArrayList<Integer> ans = new ArrayList<Integer>();
		ans.add(0);
		DFS(ans, 0, adj, new boolean[n]);
		int[] start = new int[n];
		int[] end = new int[n];
		for(int i = 0; i < 2 * n; i++) {
			if(start[ans.get(i)] != 0) end[ans.get(i)] = i + 1;
			else start[ans.get(i)] = i + 1;
		}
		for(int i = 0; i < n; i++)
			System.out.println(start[i] + " " + end[i]);
	}
	public static void DFS(ArrayList<Integer> ans, int curr, ArrayList<Integer>[] adj, boolean[] visited) {
		visited[curr] = true;
		for(int e: adj[curr]) if(!visited[e]) ans.add(e);
		ans.add(curr);
		for(int i = adj[curr].size() - 1; i >= 0; i--)
			if(!visited[adj[curr].get(i)])
				DFS(ans, adj[curr].get(i), adj, visited);
	}
	public static String next() throws IOException {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			String line = br.readLine();
			if (line == null)
				throw new IOException();
			tokenizer = new StringTokenizer(line);
		}
		return tokenizer.nextToken();
	}

	public static int nextInt() throws IOException {
		return Integer.parseInt(next());
	}

	public static long nextLong() throws IOException {
		return Long.parseLong(next());
	}

	public static double nextDouble() throws IOException {
		return Double.parseDouble(next());
	}
}


import java.util.*;
import java.io.*;
public class TestD {

	static BufferedReader br;
	static StringTokenizer tokenizer;

	public static void main(String[] args) throws Exception {
		br = new BufferedReader(new InputStreamReader(System.in));
		int n = nextInt();
		ArrayList<Integer>[] adj = new ArrayList[n];
		for(int i = 0; i < n; i++)
			adj[i] = new ArrayList<Integer>();
		for(int i = 0; i < n - 1; i++) {
			int a = nextInt() - 1;
			int b = nextInt() - 1;
			adj[a].add(b);
			adj[b].add(a);
		}
		ArrayList<Integer> ans = new ArrayList<Integer>();
		ans.add(0);
		DFS(ans, 0, adj, new boolean[n]);
		int[] start = new int[n];
		int[] end = new int[n];
		for(int i = 0; i < 2 * n; i++) {
			if(start[ans.get(i)] != 0) end[ans.get(i)] = i + 1;
			else start[ans.get(i)] = i + 1;
		}
		PrintWriter out = new PrintWriter(System.out);
		for(int i = 0; i < n; i++)
			out.println(start[i] + " " + end[i]);
		out.close();
	}
	public static void DFS(ArrayList<Integer> ans, int curr, ArrayList<Integer>[] adj, boolean[] visited) {
		visited[curr] = true;
		for(int e: adj[curr]) if(!visited[e]) ans.add(e);
		ans.add(curr);
		for(int i = adj[curr].size() - 1; i >= 0; i--)
			if(!visited[adj[curr].get(i)])
				DFS(ans, adj[curr].get(i), adj, visited);
	}
	public static String next() throws IOException {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			String line = br.readLine();
			if (line == null)
				throw new IOException();
			tokenizer = new StringTokenizer(line);
		}
		return tokenizer.nextToken();
	}

	public static int nextInt() throws IOException {
		return Integer.parseInt(next());
	}

	public static long nextLong() throws IOException {
		return Long.parseLong(next());
	}

	public static double nextDouble() throws IOException {
		return Double.parseDouble(next());
	}
}


import java.util.*;
import java.io.*;
public class TestD {

	static BufferedReader br;
	static StringTokenizer tokenizer;

	public static void main(String[] args) throws Exception {
		br = new BufferedReader(new InputStreamReader(System.in));
		int n = nextInt();
		ArrayList<Integer>[] adj = new ArrayList[n];
		for(int i = 0; i < n; i++)
			adj[i] = new ArrayList<Integer>();
		for(int i = 0; i < n - 1; i++) {
			int a = nextInt() - 1;
			int b = nextInt() - 1;
			adj[a].add(b);
			adj[b].add(a);
		}
		adj = convertToDirected(adj, 0);
		ArrayList<Integer> ans = new ArrayList<Integer>();
		ans.add(0);
		DFS(ans, 0, adj);
		int[] start = new int[n];
		int[] end = new int[n];
		for(int i = 0; i < 2 * n; i++) {
			if(start[ans.get(i)] != 0) end[ans.get(i)] = i + 1;
			else start[ans.get(i)] = i + 1;
		}
		for(int i = 0; i < n; i++)
			System.out.println(start[i] + " " + end[i]);
	}
	public static void DFS(ArrayList<Integer> ans, int curr, ArrayList<Integer>[] adj) {
		for(int e: adj[curr]) ans.add(e);
		ans.add(curr);
		for(int i = adj[curr].size() - 1; i >= 0; i--)
			DFS(ans, adj[curr].get(i), adj);
	}
	//converts undirected adj tree to one directed downwards from root
		public static ArrayList<Integer>[] convertToDirected(ArrayList<Integer>[] adj, int root) {
			ArrayList<Integer>[] adj1 = new ArrayList[adj.length];
			for(int i = 0; i < adj.length; i++)
				adj1[i] = new ArrayList<Integer>();
			ArrayDeque<Integer> q = new ArrayDeque<Integer>();
			q.add(root);
			boolean[] visited = new boolean[adj.length];
			while(!q.isEmpty()) {
				int curr = q.remove();
				visited[curr] = true;
				for(int i = 0; i < adj[curr].size(); i++) {
					if(!visited[adj[curr].get(i)]) {
						adj1[curr].add(adj[curr].get(i));
						q.add(adj[curr].get(i));
					}
				}
			}
			return adj1;
		}
	public static String next() throws IOException {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			String line = br.readLine();
			if (line == null)
				throw new IOException();
			tokenizer = new StringTokenizer(line);
		}
		return tokenizer.nextToken();
	}

	public static int nextInt() throws IOException {
		return Integer.parseInt(next());
	}

	public static long nextLong() throws IOException {
		return Long.parseLong(next());
	}

	public static double nextDouble() throws IOException {
		return Double.parseDouble(next());
	}
}


import java.util.*;
import java.io.*;
public class TestD {

	static BufferedReader br;
	static StringTokenizer tokenizer;

	public static void main(String[] args) throws Exception {
		br = new BufferedReader(new InputStreamReader(System.in));
		int n = nextInt();
		ArrayList<Integer>[] adj = new ArrayList[n];
		for(int i = 0; i < n; i++)
			adj[i] = new ArrayList<Integer>();
		for(int i = 0; i < n - 1; i++) {
			int a = nextInt() - 1;
			int b = nextInt() - 1;
			adj[a].add(b);
			adj[b].add(a);
		}
		adj = convertToDirected(adj, 0);
		ArrayList<Integer> ans = new ArrayList<Integer>();
		ans.add(0);
		DFS(ans, 0, adj);
		int[] start = new int[n];
		int[] end = new int[n];
		for(int i = 0; i < 2 * n; i++) {
			if(start[ans.get(i)] != 0) end[ans.get(i)] = i + 1;
			else start[ans.get(i)] = i + 1;
		}
		System.out.println(ans);
		for(int i = 0; i < n; i++)
			System.out.println(start[i] + " " + end[i]);
	}
	public static void DFS(ArrayList<Integer> ans, int curr, ArrayList<Integer>[] adj) {
		for(int e: adj[curr]) ans.add(e);
		ans.add(curr);
		for(int i = adj[curr].size() - 1; i >= 0; i--)
			DFS(ans, adj[curr].get(i), adj);
	}
	//converts undirected adj tree to one directed downwards from root
		public static ArrayList<Integer>[] convertToDirected(ArrayList<Integer>[] adj, int root) {
			ArrayList<Integer>[] adj1 = new ArrayList[adj.length];
			for(int i = 0; i < adj.length; i++)
				adj1[i] = new ArrayList<Integer>();
			ArrayDeque<Integer> q = new ArrayDeque<Integer>();
			q.add(root);
			boolean[] visited = new boolean[adj.length];
			while(!q.isEmpty()) {
				int curr = q.remove();
				visited[curr] = true;
				for(int i = 0; i < adj[curr].size(); i++) {
					if(!visited[adj[curr].get(i)]) {
						adj1[curr].add(adj[curr].get(i));
						q.add(adj[curr].get(i));
					}
				}
			}
			return adj1;
		}
	public static String next() throws IOException {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			String line = br.readLine();
			if (line == null)
				throw new IOException();
			tokenizer = new StringTokenizer(line);
		}
		return tokenizer.nextToken();
	}

	public static int nextInt() throws IOException {
		return Integer.parseInt(next());
	}

	public static long nextLong() throws IOException {
		return Long.parseLong(next());
	}

	public static double nextDouble() throws IOException {
		return Double.parseDouble(next());
	}
}


import java.util.*;
import java.io.*;

public class Main {
	public static void main(String args[]) {new Main().run();}

	FastReader in = new FastReader();
	PrintWriter out = new PrintWriter(System.out);
	void run(){
		work();
		out.flush();
	}
	ArrayList<Integer>[] graph;
	int[][] ret;
	int[] degree;
	int max;
	void work() {
		int n=in.nextInt();
		graph=(ArrayList<Integer>[])new ArrayList[n];
		for(int i=0;i<n;i++) {
			graph[i]=new ArrayList<>();
		}
		ret=new int[n][];
		degree=new int[n];
		for(int i=0;i<n-1;i++) {
			int n1=in.nextInt()-1;
			int n2=in.nextInt()-1;
			graph[n1].add(n2);
			graph[n2].add(n1);
			degree[n1]++;
			degree[n2]++;
		}
		dfs(0,new boolean[n],0);
		for(int i=0;i<n;i++) {
			out.println((ret[i][0]+1)+" "+(ret[i][1]+1));
		}
	}
	private void dfs(int node,boolean[] vis,int cur) {
		vis[node]=true;
		int d=degree[node];
		ret[node]=new int[] {cur,max+d+1};
		int p=max+d;
		max+=d+1;
		for(int nn:graph[node]) {
			if(!vis[nn]) {
				degree[nn]--;
				dfs(nn,vis,p--);
			}
		}
	}
}

class FastReader
{
	BufferedReader br;
	StringTokenizer st;

	public FastReader()
	{
		br=new BufferedReader(new InputStreamReader(System.in));
	}

	public String next()
	{
		if(st==null || !st.hasMoreElements())
		{
			try {
				st = new StringTokenizer(br.readLine());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return st.nextToken();
	}

	public int nextInt()
	{
		return Integer.parseInt(next());
	}

	public long nextLong()
	{
		return Long.parseLong(next());
	}
}


//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) {
        out.println(s+1);
        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();
    }
}


//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();
    }
}


#include <bits/stdc++.h>
using namespace std;
struct _IO{_IO(){ios::sync_with_stdio(0);cin.tie(0);}}_io;
typedef long long ll; typedef long double db;
const int N = 1e6 + 5, M = 1e9 + 7;

vector<int> G[N];

int l[N], r[N], tot;

void dfs(int u, int f) {
  vector<int> rev;
  for (int v : G[u]) {
    if (v != f) {
      l[v] = ++tot;
    }
  }
  r[u] = ++tot;
  reverse(G[u].begin(), G[u].end());
  for (int v : G[u]) {
    if (v != f) {
      dfs(v, u);
    }
  }
}

int main() {
  int n;
  cin >> n;
  int u, v;
  for (int i = 1; i < n; i++) {
    cin >> u >> v;
    G[u].push_back(v);
    G[v].push_back(u);
  }
  l[1] = ++tot;
  dfs(1, 0);
  for (int i = 1; i <= n; i++) {
    cout << l[i] << ' ' << r[i] << '\n';
  }
}


#include <bits/stdc++.h>
using namespace std;
struct _IO{_IO(){ios::sync_with_stdio(0);cin.tie(0);}}_io;
typedef long long ll; typedef long double db;
const int N = 1e6 + 5, M = 1e9 + 7;

vector<int> G[N];

int l[N], r[N], tot;

void dfs(int u, int f) {
  vector<int> rev;
  for (int v : G[u]) {
    if (v != f) {
      rev.push_back(v);
      l[v] = ++tot;
    }
  }
  r[u] = ++tot;
  for (int v : rev) {
    if (v != f) {
      dfs(v, u);
    }
  }
}

int main() {
  int n;
  cin >> n;
  int u, v;
  for (int i = 1; i < n; i++) {
    cin >> u >> v;
    G[u].push_back(v);
    G[v].push_back(u);
  }
  l[1] = ++tot;
  dfs(1, 0);
  for (int i = 1; i <= n; i++) {
    cout << l[i] << ' ' << r[i] << '\n';
  }
}


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

string to_string(string s) { return '"' + s + '"'; }
string to_string(bool b) { return b ? "true" : "false"; }
template <size_t N> string to_string(bitset<N> bs) {
  string res;
  for (size_t i = 0; i < N; ++i) res += '0' + bs[i];
  return res;
}
string to_string(vector<bool> v) {
  string res = "{";
  for (bool e : v) res += to_string(e) + ", ";
  return res += "}";
}

template <class T, class U> string to_string(pair<T, U> p);
template <class C> string to_string(C c) {
  string res = "{";
  for (auto e : c) res += to_string(e) + ", ";
  return res += "}";
}
template <class T, class U> string to_string(pair<T, U> p) {
  return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}

void debug() { cerr << '\n'; }
template <class Head, class... Tail> void debug(Head head, Tail... tail) {
  cerr << ' ' << to_string(head), debug(tail...);
}
#ifdef LOCAL
#define DEBUG(...) cerr << "[" << #__VA_ARGS__ << "]:", debug(__VA_ARGS__)
#else
#define DEBUG(...)
#endif

int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  int n;
  cin >> n;
  vector< vector<int> > g(n);
  for (int _ = n - 1; _--; ) {
    int u, v;
    cin >> u >> v;
    --u, --v;
    g[u].push_back(v);
    g[v].push_back(u);
  }
  vector< deque<int> > d(n);
  auto dfs = [&](auto&& F, int v, int p) -> void {
    d[v] = {v, v};
    for (int u : g[v]) {
      if (u != p) {
        F(F, u, v);
        if (d[v].size() < d[u].size()) {
          swap(d[v], d[u]);
          int fv = d[v].front();
          d[v].pop_front();
          int fu = d[u].front();
          d[u].pop_front();
          while (not d[u].empty()) {
            d[v].push_front(d[u].back());
            d[u].pop_back();
          }
          d[v].push_front(fv);
          d[v].push_front(fu);
        } else {
          int t = d[v].front();
          d[v].pop_front();
          d[v].push_front(d[u].front());
          d[u].pop_front();
          d[v].push_front(t);
          while (not d[u].empty()) {
            d[v].push_back(d[u].front());
            d[u].pop_front();
          }
        }
      }
    }
  };
  dfs(dfs, 0, -1);
  DEBUG(d[0]);
  vector< vector<int> > res(n);
  for (int i = 0; i < 2 * n; ++i) {
    res[d[0][i]].push_back(i);
  }
  for (auto e : res) {
    cout << e[0] + 1 << ' ' << e[1] + 1 << '\n';
  }
}


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

string to_string(string s) { return '"' + s + '"'; }
string to_string(bool b) { return b ? "true" : "false"; }
template <size_t N> string to_string(bitset<N> bs) {
  string res;
  for (size_t i = 0; i < N; ++i) res += '0' + bs[i];
  return res;
}
string to_string(vector<bool> v) {
  string res = "{";
  for (bool e : v) res += to_string(e) + ", ";
  return res += "}";
}

template <class T, class U> string to_string(pair<T, U> p);
template <class C> string to_string(C c) {
  string res = "{";
  for (auto e : c) res += to_string(e) + ", ";
  return res += "}";
}
template <class T, class U> string to_string(pair<T, U> p) {
  return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}

void debug() { cerr << '\n'; }
template <class Head, class... Tail> void debug(Head head, Tail... tail) {
  cerr << ' ' << to_string(head), debug(tail...);
}
#ifdef LOCAL
#define DEBUG(...) cerr << "[" << #__VA_ARGS__ << "]:", debug(__VA_ARGS__)
#else
#define DEBUG(...)
#endif

int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  int n;
  cin >> n;
  vector< vector<int> > g(n);
  for (int _ = n - 1; _--; ) {
    int u, v;
    cin >> u >> v;
    --u, --v;
    g[u].push_back(v);
    g[v].push_back(u);
  }
  vector< deque<int> > d(n);
  auto dfs = [&](auto&& F, int v, int p) -> void {
    d[v] = {v, v};
    for (int u : g[v]) {
      if (u != p) {
        F(F, u, v);
        if (d[v].size() < d[u].size()) {
          swap(d[v], d[u]);
          int fv = d[v].front();
          d[v].pop_front();
          int fu = d[u].front();
          d[u].pop_front();
          while (not d[u].empty()) {
            d[v].push_front(d[u].back());
            d[u].pop_back();
          }
          d[v].push_front(fv);
          d[v].push_front(fu);
        } else {
          int t = d[v].front();
          d[v].pop_front();
          d[v].push_front(d[u].front());
          d[u].pop_front();
          d[v].push_front(t);
          while (not d[u].empty()) {
            d[v].push_back(d[u].front());
            d[u].pop_front();
          }
        }
        assert(d[u].empty());
        d[u].shrink_to_fit();
      }
    }
  };
  dfs(dfs, 0, -1);
  DEBUG(d[0]);
  vector< vector<int> > res(n);
  for (int i = 0; i < 2 * n; ++i) {
    res[d[0][i]].push_back(i);
  }
  for (auto e : res) {
    cout << e[0] + 1 << ' ' << e[1] + 1 << '\n';
  }
}


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

string to_string(string s) { return '"' + s + '"'; }
string to_string(bool b) { return b ? "true" : "false"; }
template <size_t N> string to_string(bitset<N> bs) {
  string res;
  for (size_t i = 0; i < N; ++i) res += '0' + bs[i];
  return res;
}
string to_string(vector<bool> v) {
  string res = "{";
  for (bool e : v) res += to_string(e) + ", ";
  return res += "}";
}

template <class T, class U> string to_string(pair<T, U> p);
template <class C> string to_string(C c) {
  string res = "{";
  for (auto e : c) res += to_string(e) + ", ";
  return res += "}";
}
template <class T, class U> string to_string(pair<T, U> p) {
  return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}

void debug() { cerr << '\n'; }
template <class Head, class... Tail> void debug(Head head, Tail... tail) {
  cerr << ' ' << to_string(head), debug(tail...);
}
#ifdef LOCAL
#define DEBUG(...) cerr << "[" << #__VA_ARGS__ << "]:", debug(__VA_ARGS__)
#else
#define DEBUG(...)
#endif

int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  int n;
  cin >> n;
  vector< vector<int> > g(n);
  for (int _ = n - 1; _--; ) {
    int u, v;
    cin >> u >> v;
    --u, --v;
    g[u].push_back(v);
    g[v].push_back(u);
  }
  vector< deque<int> > d(n);
  auto dfs = [&](auto&& F, int v, int p) -> void {
    d[v] = {v, v};
    for (int u : g[v]) {
      if (u != p) {
        F(F, u, v);
        if (d[v].size() < d[u].size()) {
          swap(d[v], d[u]);
        }
        assert(not d[v].empty());
        int t = d[v].front();
        d[v].pop_front();
        d[v].push_front(d[u].front());
        d[u].pop_front();
        d[v].push_front(t);
        while (not d[u].empty()) {
          d[v].push_back(d[u].front());
          d[u].pop_front();
        }
      }
    }
  };
  dfs(dfs, 0, -1);
  DEBUG(d[0]);
  vector< vector<int> > res(n);
  for (int i = 0; i < 2 * n; ++i) {
    res[d[0][i]].push_back(i);
  }
  for (auto e : res) {
    cout << e[0] + 1 << ' ' << e[1] + 1 << '\n';
  }
}


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

string to_string(string s) { return '"' + s + '"'; }
string to_string(bool b) { return b ? "true" : "false"; }
template <size_t N> string to_string(bitset<N> bs) {
  string res;
  for (size_t i = 0; i < N; ++i) res += '0' + bs[i];
  return res;
}
string to_string(vector<bool> v) {
  string res = "{";
  for (bool e : v) res += to_string(e) + ", ";
  return res += "}";
}

template <class T, class U> string to_string(pair<T, U> p);
template <class C> string to_string(C c) {
  string res = "{";
  for (auto e : c) res += to_string(e) + ", ";
  return res += "}";
}
template <class T, class U> string to_string(pair<T, U> p) {
  return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}

void debug() { cerr << '\n'; }
template <class Head, class... Tail> void debug(Head head, Tail... tail) {
  cerr << ' ' << to_string(head), debug(tail...);
}
#ifdef LOCAL
#define DEBUG(...) cerr << "[" << #__VA_ARGS__ << "]:", debug(__VA_ARGS__)
#else
#define DEBUG(...)
#endif

int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  int n;
  cin >> n;
  vector< vector<int> > g(n);
  for (int _ = n - 1; _--; ) {
    int u, v;
    cin >> u >> v;
    --u, --v;
    g[u].push_back(v);
    g[v].push_back(u);
  }
  vector< deque<int> > d(n);
  auto dfs = [&](auto&& F, int v, int p) -> void {
    d[v] = {v, v};
    for (int u : g[v]) {
      if (u != p) {
        F(F, u, v);
        if (d[v].size() < d[u].size()) {
          swap(d[v], d[u]);
          int fv = d[v].front();
          d[v].pop_front();
          int fu = d[u].front();
          d[u].pop_front();
          while (not d[u].empty()) {
            d[v].push_front(d[u].back());
            d[u].pop_back();
          }
          d[v].push_front(fv);
          d[v].push_front(fu);
        } else {
          int t = d[v].front();
          d[v].pop_front();
          d[v].push_front(d[u].front());
          d[u].pop_front();
          d[v].push_front(t);
          while (not d[u].empty()) {
            d[v].push_back(d[u].front());
            d[u].pop_front();
          }
        }
        deque<int>().swap(d[u]);
      }
    }
  };
  dfs(dfs, 0, -1);
  DEBUG(d[0]);
  vector< vector<int> > res(n);
  for (int i = 0; i < 2 * n; ++i) {
    res[d[0][i]].push_back(i);
  }
  for (auto e : res) {
    cout << e[0] + 1 << ' ' << e[1] + 1 << '\n';
  }
}


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

string to_string(string s) { return '"' + s + '"'; }
string to_string(bool b) { return b ? "true" : "false"; }
template <size_t N> string to_string(bitset<N> bs) {
  string res;
  for (size_t i = 0; i < N; ++i) res += '0' + bs[i];
  return res;
}
string to_string(vector<bool> v) {
  string res = "{";
  for (bool e : v) res += to_string(e) + ", ";
  return res += "}";
}

template <class T, class U> string to_string(pair<T, U> p);
template <class C> string to_string(C c) {
  string res = "{";
  for (auto e : c) res += to_string(e) + ", ";
  return res += "}";
}
template <class T, class U> string to_string(pair<T, U> p) {
  return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}

void debug() { cerr << '\n'; }
template <class Head, class... Tail> void debug(Head head, Tail... tail) {
  cerr << ' ' << to_string(head), debug(tail...);
}
#ifdef LOCAL
#define DEBUG(...) cerr << "[" << #__VA_ARGS__ << "]:", debug(__VA_ARGS__)
#else
#define DEBUG(...)
#endif

int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  int n;
  cin >> n;
  vector< vector<int> > g(n);
  for (int _ = n - 1; _--; ) {
    int u, v;
    cin >> u >> v;
    --u, --v;
    g[u].push_back(v);
    g[v].push_back(u);
  }
  vector< unique_ptr< deque<int> > > d(n);
  auto dfs = [&](auto&& F, int v, int p) -> void {
    d[v] = make_unique< deque<int> >();
    *d[v] = {v, v};
    for (int u : g[v]) {
      if (u != p) {
        F(F, u, v);
        if ((*d[v]).size() < (*d[u]).size()) {
          swap((*d[v]), (*d[u]));
          int fv = (*d[v]).front();
          (*d[v]).pop_front();
          int fu = (*d[u]).front();
          (*d[u]).pop_front();
          while (not (*d[u]).empty()) {
            (*d[v]).push_front((*d[u]).back());
            (*d[u]).pop_back();
          }
          (*d[v]).push_front(fv);
          (*d[v]).push_front(fu);
        } else {
          int t = (*d[v]).front();
          (*d[v]).pop_front();
          (*d[v]).push_front((*d[u]).front());
          (*d[u]).pop_front();
          (*d[v]).push_front(t);
          while (not (*d[u]).empty()) {
            (*d[v]).push_back((*d[u]).front());
            (*d[u]).pop_front();
          }
        }
        d[u]->shrink_to_fit();
      }
    }
  };
  dfs(dfs, 0, -1);
  // DEBUG(d[0]);
  vector< vector<int> > res(n);
  for (int i = 0; i < 2 * n; ++i) {
    res[(*d[0])[i]].push_back(i);
  }
  for (auto e : res) {
    cout << e[0] + 1 << ' ' << e[1] + 1 << '\n';
  }
}


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

string to_string(string s) { return '"' + s + '"'; }
string to_string(bool b) { return b ? "true" : "false"; }
template <size_t N> string to_string(bitset<N> bs) {
  string res;
  for (size_t i = 0; i < N; ++i) res += '0' + bs[i];
  return res;
}
string to_string(vector<bool> v) {
  string res = "{";
  for (bool e : v) res += to_string(e) + ", ";
  return res += "}";
}

template <class T, class U> string to_string(pair<T, U> p);
template <class C> string to_string(C c) {
  string res = "{";
  for (auto e : c) res += to_string(e) + ", ";
  return res += "}";
}
template <class T, class U> string to_string(pair<T, U> p) {
  return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}

void debug() { cerr << '\n'; }
template <class Head, class... Tail> void debug(Head head, Tail... tail) {
  cerr << ' ' << to_string(head), debug(tail...);
}
#ifdef LOCAL
#define DEBUG(...) cerr << "[" << #__VA_ARGS__ << "]:", debug(__VA_ARGS__)
#else
#define DEBUG(...)
#endif

int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  int n;
  cin >> n;
  vector< vector<int> > g(n);
  for (int _ = n - 1; _--; ) {
    int u, v;
    cin >> u >> v;
    --u, --v;
    g[u].push_back(v);
    g[v].push_back(u);
  }
  vector< unique_ptr< deque<int> > > d(n);
  auto dfs = [&](auto&& F, int v, int p) -> void {
    d[v] = make_unique< deque<int> >();
    *d[v] = {v, v};
    for (int u : g[v]) {
      if (u != p) {
        F(F, u, v);
        if ((*d[v]).size() < (*d[u]).size()) {
          swap((*d[v]), (*d[u]));
          int fv = (*d[v]).front();
          (*d[v]).pop_front();
          int fu = (*d[u]).front();
          (*d[u]).pop_front();
          while (not (*d[u]).empty()) {
            (*d[v]).push_front((*d[u]).back());
            (*d[u]).pop_back();
          }
          (*d[v]).push_front(fv);
          (*d[v]).push_front(fu);
        } else {
          int t = (*d[v]).front();
          (*d[v]).pop_front();
          (*d[v]).push_front((*d[u]).front());
          (*d[u]).pop_front();
          (*d[v]).push_front(t);
          while (not (*d[u]).empty()) {
            (*d[v]).push_back((*d[u]).front());
            (*d[u]).pop_front();
          }
        }
      }
    }
  };
  dfs(dfs, 0, -1);
  // DEBUG(d[0]);
  vector< vector<int> > res(n);
  for (int i = 0; i < 2 * n; ++i) {
    res[(*d[0])[i]].push_back(i);
  }
  for (auto e : res) {
    cout << e[0] + 1 << ' ' << e[1] + 1 << '\n';
  }
}


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

template <class T> struct Deque {
  vector<T> l, r;
  void build(vector<T> v) {
    l = {rend(v) - v.size() / 2, rend(v)};
    r = {begin(v) + v.size() / 2, end(v)};
  }
  void push_front(T a) { l.push_back(a); }
  void push_back(T a) { r.push_back(a); }
  void pop_front() {
    if (l.empty()) build({++begin(r), end(r)});
    else l.pop_back();
  }
  void pop_back() {
    if (r.empty()) build({++rbegin(l), rend(l)});
    else r.pop_back();
  }
  size_t size() const { return l.size() + r.size(); }
  T& operator[](size_t i) {
    return i < l.size() ? l[l.size() - i - 1] : r[i - l.size()];
  }
  T operator[](size_t i) const {
    return i < l.size() ? l[l.size() - i - 1] : r[i - l.size()];
  }
  T front() const { return (*this)[0]; }
  T back() const { return (*this)[size() - 1]; }
};

int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  int n;
  cin >> n;
  vector< vector<int> > g(n);
  for (int _ = n - 1; _--; ) {
    int u, v;
    cin >> u >> v;
    --u, --v;
    g[u].push_back(v);
    g[v].push_back(u);
  }
  vector< Deque<int> > d(n);
  auto dfs = [&](auto&& F, int v, int p) -> void {
    d[v].build({v, v});
    for (int u : g[v]) {
      if (u != p) {
        F(F, u, v);
        if (d[v].size() < d[u].size()) {
          swap(d[v], d[u]);
          int fv = d[v].front();
          d[v].pop_front();
          int fu = d[u].front();
          d[u].pop_front();
          while (d[u].size()) {
            d[v].push_front(d[u].back());
            d[u].pop_back();
          }
          d[v].push_front(fv);
          d[v].push_front(fu);
        } else {
          int t = d[v].front();
          d[v].pop_front();
          d[v].push_front(d[u].front());
          d[u].pop_front();
          d[v].push_front(t);
          while (d[u].size()) {
            d[v].push_back(d[u].front());
            d[u].pop_front();
          }
        }
      }
    }
  };
  dfs(dfs, 0, -1);
  vector< vector<int> > res(n);
  for (int i = 0; i < 2 * n; ++i) {
    res[d[0][i]].push_back(i);
  }
  for (auto e : res) {
    cout << e[0] + 1 << ' ' << e[1] + 1 << '\n';
  }
}


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

template <class T> struct Deque {
  vector<T> l, r;
  void build(vector<T> v) {
    l = {rend(v) - v.size() / 2, rend(v)};
    r = {begin(v) + v.size() / 2, end(v)};
  }
  void push_front(T a) { l.push_back(a); }
  void push_back(T a) { r.push_back(a); }
  void pop_front() {
    if (l.empty()) build({++begin(r), end(r)});
    else l.pop_back();
  }
  void pop_back() {
    if (r.empty()) build({rbegin(l), --rend(l)});
    else r.pop_back();
  }
  size_t size() const { return l.size() + r.size(); }
  T& operator[](size_t i) {
    return i < l.size() ? l[l.size() - i - 1] : r[i - l.size()];
  }
  T& front() { return (*this)[0]; }
  T& back() { return (*this)[size() - 1]; }
  friend string to_string(Deque d) {
    string res = "{";
    for (size_t i = 0; i < d.size(); ++i) res += to_string(d[i]) + ", ";
    return res += "}";
  }
};

int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  int n;
  cin >> n;
  vector< vector<int> > g(n);
  for (int _ = n - 1; _--; ) {
    int u, v;
    cin >> u >> v;
    --u, --v;
    g[u].push_back(v);
    g[v].push_back(u);
  }
  vector< Deque<int> > d(n);
  auto dfs = [&](auto&& F, int v, int p) -> void {
    // d[v].build({v, v});
    d[v].push_back(v);
    d[v].push_back(v);
    for (int u : g[v]) {
      if (u != p) {
        F(F, u, v);
        if (d[v].size() < d[u].size()) {
          swap(d[v], d[u]);
          int fv = d[v].front();
          d[v].pop_front();
          int fu = d[u].front();
          d[u].pop_front();
          while (d[u].size()) {
            d[v].push_front(d[u].back());
            d[u].pop_back();
          }
          d[v].push_front(fv);
          d[v].push_front(fu);
        } else {
          int t = d[v].front();
          d[v].pop_front();
          d[v].push_front(d[u].front());
          d[u].pop_front();
          d[v].push_front(t);
          while (d[u].size()) {
            d[v].push_back(d[u].front());
            d[u].pop_front();
          }
        }
      }
    }
  };
  dfs(dfs, 0, -1);
  vector< vector<int> > res(n);
  for (int i = 0; i < 2 * n; ++i) {
    res[d[0][i]].push_back(i);
  }
  for (auto e : res) {
    cout << e[0] + 1 << ' ' << e[1] + 1 << '\n';
  }
}


#include <bits/stdc++.h>

using namespace std;

#define f first
#define s second

const int MAXN = 5e5;

int N;
vector<int> adj[MAXN];
pair<int,int> ans[MAXN];
int dfs(int c, int p, int start, int occupied) {
  ans[c].f = start;
  ans[c].s = occupied + adj[c].size();
  if(c == 0) ans[c].s++;
  if(adj[c].size() == 1) return ans[c].s;
  int ends = ans[c].s;
  int starts = ans[c].s;
  for(int v: adj[c]) if(v != p) {
    ends = dfs(v,c,--starts, ends);
  }
  return ends;
}

int main() {
  cin >> N;
  for(int i = 0; i < N - 1; i++) {
    int a, b; cin >> a >> b; a--; b--; adj[a].push_back(b); adj[b].push_back(a);
  }
  dfs(0,0,1,1);
  for(int i = 0; i < N; i++) cout << ans[i].f << " " << ans[i].s << endl;
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define f first
#define s second

const int MAXN = 5e5;

int N;
vector<int> adj[MAXN];
pair<int,int> ans[MAXN];
int dfs(int c, int p, int start, int occupied) {
  ans[c].f = start;
  ans[c].s = occupied + adj[c].size();
  if(c == 0) ans[c].s++;
  if(c != 0 && adj[c].size() == 1) return ans[c].s;
  int ends = ans[c].s;
  int starts = ans[c].s;
  for(int v: adj[c]) if(v != p) {
    ends = dfs(v,c,--starts, ends);
  }
  return ends;
}

int main() {
  ios::sync_with_stdio(0); cin.tie(0);
  cin >> N;
  for(int i = 0; i < N - 1; i++) {
    int a, b; cin >> a >> b; a--; b--; adj[a].push_back(b); adj[b].push_back(a);
  }
  dfs(0,0,1,1);
  for(int i = 0; i < N; i++) cout << ans[i].f << " " << ans[i].s << endl;
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define f first
#define s second

const int MAXN = 5e5;

int N;
vector<int> adj[MAXN];
pair<int,int> ans[MAXN];
int dfs(int c, int p, int start, int occupied) {
  ans[c].f = start;
  ans[c].s = occupied + adj[c].size();
  if(c == 0) ans[c].s++;
  int ends = ans[c].s;
  int starts = ans[c].s;
  for(int v: adj[c]) if(v != p) {
    ends = dfs(v,c,--starts, ends);
  }
  return ends;
}

int main() {
  cin >> N;
  for(int i = 0; i < N - 1; i++) {
    int a, b; cin >> a >> b; a--; b--; adj[a].push_back(b); adj[b].push_back(a);
  }
  dfs(0,0,1,1);
  for(int i = 0; i < N; i++) cout << ans[i].f << " " << ans[i].s << endl;
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define f first
#define s second

const int MAXN = 5e5;

int N;
vector<int> adj[MAXN];
pair<int,int> ans[MAXN];
int dfs(int c, int p, int start, int occupied) {
  ans[c].f = start;
  ans[c].s = occupied + adj[c].size();
  if(c == 0) ans[c].s++;
  if(c != 0 && adj[c].size() == 1) return ans[c].s;
  int ends = ans[c].s;
  int starts = ans[c].s;
  for(int v: adj[c]) if(v != p) {
    ends = dfs(v,c,--starts, ends);
  }
  return ends;
}

int main() {
  cin >> N;
  for(int i = 0; i < N - 1; i++) {
    int a, b; cin >> a >> b; a--; b--; adj[a].push_back(b); adj[b].push_back(a);
  }
  dfs(0,0,1,1);
  for(int i = 0; i < N; i++) cout << ans[i].f << " " << ans[i].s << endl;
  return 0;
}


import string
t = string.ascii_lowercase
t2 = list(t)
#print(t2)
n , m = map(int,input().split())
s = input()

for i in range(m):
    x , y = input().split()

    index_x = t2.index(x)
    index_y = t2.index(y)
    t2[index_x] , t2[index_y] = t2[index_y] , t2[index_x]

#print(t2)
for i in s :
    index = ord(i) - ord('a')
    print(t2[index] , end = '')


n , k = map(int,input().split())
s = list(input())

a = []
for i in range(k):
    x , y = input().split()
    for j in range(len(s)):
        if s[j] == x :
            s[j] = y

        elif s[j] == y :
            s[j] = x

print(s)


n , k = map(int,input().split())
s = list(input())

a = []
for i in range(k):
    x , y = input().split()
    for j in range(len(s)):
        if s[j] == x :
            s[j] = y

        elif s[j] == y :
            s[j] = x

print(''.join(s))


import string
n, m = map(int, input().split())
word = list(input())
alphabet = list(string.ascii_lowercase)

alphabet_dict = {}
for i in range(len(alphabet)):
    alphabet_dict[alphabet[i]] = alphabet[i]

for i in range(m):
    x, y = input().split()
    for letter in alphabet_dict:
        if alphabet_dict[letter] == x:
            alphabet_dict[letter] = y
        elif alphabet_dict[letter] == y:
            alphabet_dict[letter] = x

for i in range(len(word)):
    word[i] = alphabet_dict[word[i]]

print("".join(word))


import string
n, m = map(int, input().split())
word = list(input())
alphabet = list(string.ascii_lowercase)

alphabet_dict = {}
for i in range(len(alphabet)):
	alphabet_dict[alphabet[i]] = alphabet[i]

for i in range(m):
	x, y = input().split()
	for letter in alphabet_dict:
		if alphabet_dict[letter] == x:
			alphabet_dict[letter] = y
		elif alphabet_dict[letter] == y:
			alphabet_dict[letter] = x

print(alphabet_dict)

for i in range(len(word)):
	word[i] = alphabet_dict[word[i]]

print("".join(word))


n, m = map(int, input().split())
s = input()
for i in range(m):
    xi, yi = input().split()
    s = s.replace(xi, "X")
    s = s.replace(yi, xi)
    s = s.replace("X", yi)
print(s)


n, m = map(int, input().split())
s = input()

d = {}
for i in "abcdefghijklmnopqrstuvwxyz":
    d[i] = []

for j, l in enumerate(s):
    d[l].append(j)

for i in range(m):
    xi, yi = input().split()
    d[xi], d[yi] = d[yi], d[xi]

r = {}
for k, v in d.items():
    for pos in v:
        r[pos] = k

for l in sorted(r.items()):
    print(l[1], end="")


letters, designers = [int(x) for x in input().split(' ')]
name = input()
alphabet = [(x + 97) for x in range(26)]

for _ in range(designers):
	letter1, letter2 = input().split(' ')
	for i in range(26):
		if alphabet[i] == ord(letter1):
			alphabet[i] = ord(letter2)
		elif alphabet[i] == ord(letter2):
			alphabet[i] = ord(letter1)

for letter in name:
	print(chr(alphabet[ord(letter) - 97]), end='')
print()


letters, designers = [int(x) for x in input().split(' ')]
name = input()
alphabet = [(x + 97) for x in range(26)]

for _ in range(designers):
	letter1, letter2 = input().split(' ')
	for i in range(26):
		if alphabet[i] == ord(letter1):
			alphabet[i] = ord(letter2)
			break
		elif alphabet[i] == ord(letter2):
			alphabet[i] = ord(letter1)
			break

for letter in name:
	print(chr(alphabet[ord(letter) - 97]), end='')
print()


letters, designers = [int(x) for x in input().split(' ')]
name = input()
alphabet = [(x + 97) for x in range(26)]

for _ in range(designers):
	letter1, letter2 = input().split(' ')
	count = 0
	for i in range(26):
		if alphabet[i] == ord(letter1):
			alphabet[i] = ord(letter2)
			count += 1
		elif alphabet[i] == ord(letter2):
			alphabet[i] = ord(letter1)
			count += 1
		if count == 2:
			break

for letter in name:
	print(chr(alphabet[ord(letter) - 97]), end='')
print()


letters, designers = [int(x) for x in input().split(' ')]
name = input()
alphabet_dict = {x: x for x in range(26)}
alphabet_arr = [(x + 97) for x in range(26)]

def print_dict(dict_al):
	for key, value in dict_al.items():
		print('{}: {}'.format(chr(key), chr(value)))

for _ in range(designers):
	letter1, letter2 = input().split(' ')
	who_has_1 = alphabet_dict[ord(letter1) - 97]
	who_has_2 = alphabet_dict[ord(letter2) - 97]
	alphabet_arr[who_has_1] = ord(letter2)
	alphabet_arr[who_has_2] = ord(letter1)
	alphabet_dict[ord(letter1) - 97] = who_has_2
	alphabet_dict[ord(letter2) - 97] = who_has_1

for letter in name:
	print(chr(alphabet_arr[ord(letter) - 97]), end='')
print()


n, m = map(int, input().split())

name = input()
charList = [[chr(ord('a') + i),chr(ord('a') + i)] for i in range(26)]

for i in range(m):
    x, y = input().split()
    (charList[ord(y)-ord('a')][1], charList[ord(x)-ord('a')][1]) = (charList[ord(x)-ord('a')][1], charList[ord(y)-ord('a')][1])
    (charList[ord(y)-ord('a')], charList[ord(x)-ord('a')]) = (charList[ord(x)-ord('a')], charList[ord(y)-ord('a')])

charList.sort()
newName = ""
for i in range(n):
    newName = newName + charList[ord(name[i]) - ord('a')][1]

print(newName)


n, m = map(int, input().split())

name = input()

change = []

for i in range(m):
    x, y = input().split()
    if (x == y):
        pass
    else:
        change.append([x, y])

lastname = ""

for i in range(n):
    char = name [i]
    for j in range(len(change)):
        if (char == change[j][0]):
            char = change[j][1]
        elif (char == change[j][1]):
            char = change[j][0]

    lastname += char

print(lastname)


n, m = map(int, input().split())

name = input()

for i in range(m):
    newname = ""
    x, y = input().split()

    for j in range(n):
        if (name[j] == x):
            newname = newname + y
        elif (name[j] == y):
            newname = newname + x
        else:
            newname = newname + name[j]

    name = newname

print (name)


n, m = map(int, input().split())
s = input()
d = {}
for i in range(ord("a"), ord("z")):
    d[chr(i)] = chr(i)
for i in range(m):
    a, b = input().split()
    for k in d.keys():
        if d[k] == a:
            d[k] = b
            continue
        if d[k] == b:
            d[k] = a
ss = ''
for i in range(n):
    ss += d[s[i]]
print(ss)


n, m = map(int, input().split())
s = input()
s1 = ''
for i in range(ord('a'), ord('z') + 1):
    s1 += chr(i)
s2 = s1 + ""
for i in range(m):
    a, b = input().split()
    s2 = s2.replace(a, '*')
    s2 = s2.replace(b, a)
    s2 = s2.replace('*', b)

ss = ''
for i in range(n):
    ss += s2[s1.index(s[i])]
print(ss)


n, m = map(int, input().split())
s = input()
d = {}
for i in range(ord("a"), ord("z")):
    d[chr(i)] = chr(i)
for i in range(m):
    a, b = input().split()
    for k in d.keys():
        if d[k] == a:
            d[k] = b
            continue

        if d[k] == b:
            d[k] = a
ss = ''
for i in range(n):
    ss += d[s[i]]
print(ss)


n, m = map(int, input().split())
s = input()
for i in range(m):
    a, b = input().split()
    s = s.replace(a, '*')
    s = s.replace(b, a)
    s = s.replace('*', b)
print(s)


n, m = map(int, input().split())
ss = input()
s = list(ss)
for i in range(m):
    a, b = input().split()
    for j in range(n):
        if s[j] == a:
            s[j] = b
            continue
        if s[j] == b:
            s[j] = a
print(*s, sep='')


n, m = map(int, input().split())
s = input()
d = {}
for i in range(ord("a"), ord("z")):
    d[chr(i)] = chr(i)
for i in range(m):
    a, b = input().split()
    for k in d.keys():
        if d[k] == a:
            d[k] = b
            continue
        if d[k] == b:
            d[k] = a
            continue
ss = ''
for i in range(n):
    ss += d[s[i]]
print(ss)


#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
#
# Copyright © 2015 missingdays <missingdays@missingdays>
#
# Distributed under terms of the MIT license.

"""

"""

from string import ascii_lowercase
l = ascii_lowercase

[n, m] = list(map(int, input().split()))
s = input()

a = [None] * n

for i in range(n):
    a[i] = l.index(s[i])

alpha = [i for i in range(26)]

for i in range(m):
    al, bl = input().split()

    ai = l.index(al)
    bi = l.index(bl)

    ai = alpha.index(ai)
    bi = alpha.index(bi)

    alpha[ai], alpha[bi] = alpha[bi], alpha[ai]

for i in range(n):
    print(l[alpha[a[i]]], end="")
print()


import string
import sys
import traceback
from contextlib import contextmanager
from io import StringIO

AL = string.ascii_lowercase.encode('ascii')
OA = ord('a')

def transform(n, m, name, designers):
    tr = bytearray(AL)
    for x, y in reversed(designers):
        i1 = ord(x) - OA
        i2 = ord(y) - OA
        tr[i1], tr[i2] = tr[i2], tr[i1]
    table = bytes.maketrans(AL, tr)
    return name.translate(table)

def pd():
    line = input()
    t = line.encode('ascii').split()
    assert len(t) == 2, f"Invalid designer: {line}"
    return t

def main():
    n, m = map(int, input().split())
    name = input().encode('ascii')
    assert len(name) == n
    designers = [pd() for _ in range(m)]
    print(transform(n, m, name, designers).decode('ascii'))

def log(*args, **kwargs):
    print(*args, **kwargs, file=sys.stderr)

@contextmanager
def patchio(i):
    try:
        sys.stdin = StringIO(i)
        sys.stdout = StringIO()
        yield sys.stdout
    finally:
        sys.stdin = sys.__stdin__
        sys.stdout = sys.__stdout__

def do_test(k, test):
    try:
        log(f"TEST {k}")
        i, o = test
        with patchio(i) as r:
            main()
        if r.getvalue() == o:
            log("OK\n")
        else:
            log(f"Expected:\n{o}Got:\n{r.getvalue()}")
    except Exception:
        traceback.print_exc()
        log()

def test(ts):
    for k in ts or range(len(tests)):
        do_test(k, tests[k])

tests = [("""\
6 1
police
p m
""", """\
molice
"""), ("""\
11 6
abacabadaba
a b
b c
a d
e g
f a
b b
""", """\
cdcbcdcfcdc
""")]

if __name__ == '__main__':
    from argparse import ArgumentParser
    parser = ArgumentParser()
    parser.add_argument('--test', '-t', type=int, nargs='*')
    args = parser.parse_args()
    main() if args.test is None else test(args.test)


n,m = map(int, input().split())
ch = str(input())
res = [ch[k] for k in range(n)]
X = ["" for _ in range(m)]
Y = ["" for _ in range(m)]
for k in range(m):
    s = str(input())
    X[k] = s[0]
    Y[k] = s[2]

al = "abcdefghijklmnopqrstuvwxyz"
A = [al[k] for k in range(26)]
B = A[:]
for k in range(m):
    a = B.index(X[k])
    b = B.index(Y[k])
    A[a],A[b] = A[b],A[A]

for j in range(n):
    a = B.index(res[j])
    res[j] = A[a]

ch = ""
for k in range(n):
    ch  = ch + res[k]
print(ch)


n,m = map(int, input().split())
ch = str(input())
X = ["" for _ in range(m)]
Y = ["" for _ in range(m)]
for k in range(m):
    s = str(input())
    X[k] = s[0]
    Y[k] = s[2]
for j in range(n):
    s = ch[j]
    for k in range(m):
        if s == X[k]:
            s = Y[k]
        elif s == Y[k]:
            s = X[k]
        ch = ch[:j]+s+ch[j+1:]
print(ch)


n,m = map(int, input().split())
ch = str(input())
res = [ch[k] for k in range(n)]
X = ["" for _ in range(m)]
Y = ["" for _ in range(m)]
for k in range(m):
    s = str(input())
    X[k] = s[0]
    Y[k] = s[2]

al = "abcdefghijklmnopqrstuvwxyz"
A = [al[k] for k in range(26)]
B = A[:]
for k in range(m):
    for j in range(26):
        if A[j] == X[k]:
            A[j] = Y[k]
            break
        elif A[j] == Y[k]:
            A[j] = X[k]
            break

for j in range(n):
    a = B.index(res[j])
    res[j] = A[a]

ch = ""
for k in range(n):
    ch  = ch + res[k]
print(ch)


n,m = map(int, input().split())
ch = str(input())
res = [ch[k] for k in range(n)]
X = ["" for _ in range(m)]
Y = ["" for _ in range(m)]
for k in range(m):
    s = str(input())
    X[k] = s[0]
    Y[k] = s[2]

al = "abcdefghijklmnopqrstuvwxyz"
A = [al[k] for k in range(26)]
B = A[:]
for k in range(m):
    t = 0
    for j in range(26):
        if A[j] == X[k]:
            A[j] = Y[k]
            t += 1
        elif A[j] == Y[k]:
            A[j] = X[k]
            t += 1
        if t == 2:
            break

for j in range(n):
    a = B.index(res[j])
    res[j] = A[a]

ch = ""
for k in range(n):
    ch  = ch + res[k]
print(ch)


n,m = map(int, input().split())
ch = str(input())
X = ["" for _ in range(m)]
Y = ["" for _ in range(m)]
for k in range(m):
    s = str(input())
    X[k] = s[0]
    Y[k] = s[2]
for j in range(n):
    s = ch[j]
    for k in range(m):
        if s == X[k]:
            s = Y[k]
        elif s == Y[k]:
            s = X[k]
    ch = ch[:j]+s+ch[j+1:]
print(ch)


n,m = map(int, input().split())
ch = str(input())
res = [ch[k] for k in range(n)]
X = ["" for _ in range(m)]
Y = ["" for _ in range(m)]
for k in range(m):
    s = str(input())
    X[k] = s[0]
    Y[k] = s[2]
for j in range(n):
    s = res[j]
    for k in range(m):
        if s == X[k]:
            s = Y[k]
        elif s == Y[k]:
            s = X[k]
    res[j] = s
ch = ""
for k in range(n):
    ch  = ch + res[k]
print(ch)