You are given a tree consisting of n nodes. You want to write some labels on the tree's edges such that the following conditions hold:

  * Every label is an integer between 0 and n-2 inclusive. 
  * All the written labels are distinct. 
  * The largest value among MEX(u,v) over all pairs of nodes (u,v) is as small as possible. 



Here, MEX(u,v) denotes the smallest non-negative integer that isn't written on any edge on the unique simple path from node u to node v.

Input

The first line contains the integer n (2 ≤ n ≤ 10^5) — the number of nodes in the tree.

Each of the next n-1 lines contains two space-separated integers u and v (1 ≤ u,v ≤ n) that mean there's an edge between nodes u and v. It's guaranteed that the given graph is a tree.

Output

Output n-1 integers. The i^{th} of them will be the number written on the i^{th} edge (in the input order).

Examples

Input


3
1 2
1 3


Output


0
1


Input


6
1 2
1 3
2 4
2 5
5 6


Output


0
3
2
4
1

Note

The tree from the second sample:

<image>

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

public class C1325 {
    public static void main(String[] args) throws IOException{
        StringBuffer ans = new StringBuffer();
        StringTokenizer st;
        BufferedReader f = new BufferedReader(new InputStreamReader(System.in));
        st = new StringTokenizer(f.readLine());
        int n = Integer.parseInt(st.nextToken());
        point[] arr = new point[n];
        HashMap<Integer, ArrayList<Integer>> hash = new HashMap<>();
        point[] in = new point[n];
        for(int i = 0; i < n-1; i++){
            st = new StringTokenizer(f.readLine());
            int ft = Integer.parseInt(st.nextToken());
            int sc = Integer.parseInt(st.nextToken());
            in[i] = new point(ft, sc);
            if(arr[ft-1] == null){
                arr[ft-1] = new point(0, ft);
                hash.put(ft, new ArrayList<>());
            }
            if(arr[sc-1] == null){
                arr[sc-1] = new point(0, sc);
                hash.put(sc, new ArrayList<>());
            }
            hash.get(ft).add(sc);
            hash.get(sc).add(ft);
            arr[ft-1].x++;
            arr[sc-1].x++;
        }
        f.close();
        Arrays.sort(arr);
        //System.out.println(Arrays.toString(arr));
        //System.out.println(hash);
        HashMap<point, Integer> hashMap = new HashMap<>();
        int count = 0;
        for(int i = 0; i < n; i++){
            int curr = arr[i].y;
            for(int x = 0; x < hash.get(curr).size(); x++){
                int curry = hash.get(curr).get(x);
                if(!hashMap.containsKey(new point(curr, curry))){
                    hashMap.put(new point(curr, curry), count);
                    hashMap.put(new point(curry, curr), count);
                    count++;
                }
            }
        }
        //System.out.println(hashMap);
        for(int i = 0; i < n-1; i++){
            ans.append(hashMap.get(in[i]));
            ans.append("\n");
        }



        System.out.println(ans);
    }
    public static class point implements Comparable<point>{
        int x;
        int y;
        public point(int x,int y){
            this.x = x;
            this.y = y;
        }
        public String toString(){
            return(x + " " + y);
        }
        public boolean equals(Object x){
            point y = ((point)(x));
            if (this.x == y.x && this.y == y.y){
                return true;
            }
            return false;
        }
        public int hashCode(){
            return Objects.hash(x,y);
        }
        public int compareTo(point other){
            if(this.x > other.x || (this.x == other.x && this.y > other.y)){
                return 1;
            }else if(this.x == other.x && this.y == other.y){
                return 0;
            }
            return -1;
        }
    }

}