import java.awt.Point;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Abood2D {

	static int V, T[], L[], I[], ans[];
	static ArrayList<Integer>[] Tree;
	static ArrayList<Integer>[] Idx;
	static ArrayList<Integer>[] up;
	static SegmentTree st;

	static int N, P[][];			// P[i][j] --> the 2^j th ancestor of node i

	static void preprocessParents(int root, int[] T)	// O(n log n)
	{
		int k = 0; while(1<<k+1 < N) ++k;		// max parent = floor(log2(N - 1))

		P = new int[N][k + 1];

		for(int i = 0; i < N; i++)
			Arrays.fill(P[i], -1);

		// base case: direct parents
		for(int i = 0; i < N; ++i)
			P[i][0] = T[i];					// T[root] = -1

		for(int j = 1; j <= k; j++)
			for(int i = 0; i < N; i++)
				if(P[i][j-1] != -1)
					P[i][j] = P[P[i][j-1]][j-1];
	}

	static int query(int p, int q)		// O(log n)
	{
		//if p is situated on a higher level than q, swap them
		if (L[p] < L[q]) { p ^= q; q ^= p; p ^= q; }

		//find largest k such that 2^k is a parent of p
		int k = 0;
		while(1<<k+1 <= L[p])
			++k;

		//find the ancestor of p situated on the same level with q
		for (int i = k; i >= 0; --i)
			if (L[p] - (1<<i) >= L[q])
				p = P[p][i];

		if (p == q)
			return p;

		//go up to lowest (non-common) ancestors for p and q
		for (int i = k; i >= 0; --i)
			if (P[p][i] != -1 && P[p][i] != P[q][i])
			{
				p = P[p][i]; q = P[q][i];
			}

		return P[p][0];
	}

	static void dfs(int u, int p, int l) {
		L[u] = l;

		for (int i = 0; i < Tree[u].size(); i++) {
			int v = Tree[u].get(i);
			int k = Idx[u].get(i);

			if(v == p)
				continue;

			I[v] = k;
			T[v] = u;
			dfs(v, u, l + 1);
		}
	}

	static void dfs2(int u, int p) {
		for (int i = 0; i < up[u].size(); i++)
			st.update_range(up[u].get(i) + 1, L[u], 1);

		for (int i = 0; i < Tree[u].size(); i++) {
			int v = Tree[u].get(i);

			if(v != p)
				dfs2(v, u);
		}
		if(p != -1) {
			ans[I[u]] = st.query(L[u], L[u]);
			st.update_range(L[u], L[u], -ans[I[u]]);
		}
	}

	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner(System.in);
		PrintWriter out = new PrintWriter(System.out);

		V = sc.nextInt();
		T = new int[V];
		L = new int[V];
		I = new int[V];
		I[0] = -1;

		Tree = new ArrayList[V];
		Idx = new ArrayList[V];
		up = new ArrayList[V];
		ans = new int[V - 1];

		for (int i = 0; i < V; i++) {
			Tree[i] = new ArrayList<>();
			Idx[i] = new ArrayList<>();
			up[i] = new ArrayList<>();
		}

		for (int i = 0; i < V - 1; i++) {
			int f = sc.nextInt() - 1;
			int t = sc.nextInt() - 1;

			Tree[f].add(t);
			Tree[t].add(f);

			Idx[f].add(i);
			Idx[t].add(i);
		}

		N = V;
		dfs(0, -1, 0);
		T[0] = -1;
		preprocessParents(0, T);

		int N = 1; while(N < V) N <<= 1; //padding

		int[] in = new int[N + 1];

		st = new SegmentTree(in);

		int m = sc.nextInt();

		for (int i = 0; i < m; i++) {
			int x = sc.nextInt() - 1;
			int y = sc.nextInt() - 1;

			int p = query(x, y);
			if(L[x] != L[p])
				up[x].add(L[p]);
			if(L[y] != L[p])
				up[y].add(L[p]);

		}
		dfs2(0, -1);

		for (int i = 0; i < V - 1; i++)
			out.print(ans[i] + " ");

		out.println();

		out.flush();

	}

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

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

		SegmentTree(int[] in)
		{
			array = in; N = in.length - 1;
			sTree = new int[N<<1];		//no. of nodes = 2*N - 1, we add one to cross out index zero
			lazy = new int[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_range(int i, int j, int 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, int 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;
		}

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

		int 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);
			int q1 = query(node<<1,b,mid,i,j);
			int q2 = query(node<<1|1,mid+1,e,i,j);
			return q1 + q2;

		}
	}

	static class Scanner

	{
		StringTokenizer st;
		BufferedReader br;

		public Scanner(InputStream s){	br = new BufferedReader(new InputStreamReader(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
		{
			String x = next();
			StringBuilder sb = new StringBuilder("0");
			double res = 0, f = 1;
			boolean dec = false, neg = false;
			int start = 0;
			if(x.charAt(0) == '-')
			{
				neg = true;
				start++;
			}
			for(int i = start; i < x.length(); i++)
				if(x.charAt(i) == '.')
				{
					res = Long.parseLong(sb.toString());
					sb = new StringBuilder("0");
					dec = true;
				}
				else
				{
					sb.append(x.charAt(i));
					if(dec)
						f *= 10;
				}
			res += Long.parseLong(sb.toString()) / f;
			return res * (neg?-1:1);
		}

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

	}

}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.StringTokenizer;
import java.util.List;

public class Solver {

    StringTokenizer st;
    BufferedReader in;
    PrintWriter out;

    public static void main(String[] args) throws NumberFormatException, IOException {
        Solver solver = new Solver();
        solver.open();
        solver.solve();
        solver.close();
    }

    public void open() throws IOException {
        in = new BufferedReader(new InputStreamReader(System.in));
        out = new PrintWriter(System.out);
    }

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

    public int nextInt() throws NumberFormatException, IOException {
        return Integer.parseInt(nextToken());
    }

    public long nextLong() throws NumberFormatException, IOException {
        return Long.parseLong(nextToken());
    }

    public double nextDouble() throws NumberFormatException, IOException {
        return Double.parseDouble(nextToken());
    }

    public class Edge{
        int to;
        int id;
        public Edge(int to, int id) {
            super();
            this.to = to;
            this.id = id;
        }
    }

    List<List<Edge>> graph;
    int[] tin;
    int[] tout;
    int[] balance;
    int[] ans;
    int[][] lca;
    int timer = 0;
    int n;
    int l;

    boolean isParent(int v1,int v2){
        return tin[v1]<=tin[v2] && tout[v1]>=tout[v2];
    }

    void dfs(int v,int parent){
        tin[v] = timer++;

        lca[v][0] = parent;
        for(int i=1;i<=l;i++){
            lca[v][i] = lca[lca[v][i-1]][i-1];
        }

        for(Edge child:graph.get(v)){
            if(child.to!=parent){
                dfs(child.to, v);
            }
        }

        tout[v] = timer++;
    }

    int getLCA(int v1,int v2){
        if (isParent(v1, v2)) return v1;
        if (isParent(v2, v1)) return v2;

        int t = l;
        while (t>=0){
            if (!isParent(lca[v1][t],v2)){
                v1 = lca[v1][t];
            }
            t--;
        }
        return lca[v1][0];
    }

    int getAns(int v,int parent){
        int sum = 0;
        for(Edge edge:graph.get(v)){
            if (edge.to==parent) continue;
            ans[edge.id] = getAns(edge.to,v);
            sum += ans[edge.id];
        }

        return sum+balance[v];
    }

    public void solve() throws NumberFormatException, IOException {
        n = nextInt();
        graph = new ArrayList<List<Edge>>(n);
        tin = new int[n];
        tout = new int[n];
        lca = new int[n][];
        balance = new int[n];
        ans = new int[n-1];

        l = 1;
        while ((1<<l) <= n) l++;
        for(int i=0;i<n;i++){
            graph.add(new ArrayList<Edge>());
            lca[i] = new int[l+1];
        }
        for(int i=0;i<n-1;i++){
            int from = nextInt()-1;
            int to = nextInt()-1;
            graph.get(from).add(new Edge(to, i));
            graph.get(to).add(new Edge(from, i));
        }

        dfs(0, 0);

        int k=nextInt();
        for(int i=0;i<k;i++){
            int from = nextInt()-1;
            int to = nextInt() - 1;
            int parent = getLCA(from, to);
            balance[from]++;
            balance[to]++;
            balance[parent]-=2;
        }

        getAns(0, -1);

        for(int i=0;i<n-1;i++){
            out.print(ans[i]+" ");
        }
    }

    public void close() {
        out.flush();
        out.close();
    }

}


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class E {

    static StreamTokenizer st;
    static ArrayList<Integer>[]ages;
    static int[][]up;
    static int L = 0, timer = 0, n;
    static int[]tin,tout,cnt,ans;
    static Map<Long, Integer>ind_map = new HashMap<Long, Integer>();
    public static void main(String[] args) throws IOException{
        st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
        PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
        n = nextInt();
        ages = new ArrayList[n];
        for (int i = 0; i < n; i++) {
            ages[i] = new ArrayList<Integer>();
        }
        for (int i = 1; i < n; i++) {
            int v1 = nextInt();
            int v2 = nextInt();
            v1--;
            v2--;
            ind_map.put((long)v1*(n+1)+v2, i);
            ind_map.put((long)v2*(n+1)+v1, i);
            ages[v1].add(v2);
            ages[v2].add(v1);
        }
        while ((1 << L) <= n)
            L++;
        tin = new int[n];
        tout = new int[n];
        up = new int[n][L+1];
        dfs(0, -1);
        cnt = new int[n];
        int k = nextInt();
        for (int i = 1; i <= k; i++) {
            int v1 = nextInt();
            int v2 = nextInt();
            v1--;
            v2--;
            int lca = lca(v1, v2);
            cnt[v1]++;
            cnt[v2]++;
            cnt[lca] -= 2;
        }
        ans = new int[n];
        dfs2(0, -1);
        for (int i = 1; i < n; i++) {
            pw.print(ans[i]+" ");
        }
        pw.close();
    }

    private static void dfs2(int v, int p) {
        for (int to : ages[v]) {
            if (to != p)
                dfs2(to, v);
        }
        for (int to : ages[v]) {
            if (to != p) {
                cnt[v] += cnt[to];
            }
        }
        if (p != -1)
            ans[ind_map.get((long)v*(n+1)+p)] = cnt[v];
    }

    private static int lca(int a, int b) {
        if (upper(a, b))
            return a;
        if (upper(b, a))
            return b;
        for (int i = L; i >= 0; i--) {
            if (!upper(up[a][i], b))
                a = up[a][i];
        }
        return up[a][0];
    }

    private static boolean upper(int a, int b) {
        return tin[a] <= tin[b] && tout[a] >= tout[b];
    }

    private static void dfs(int v, int p) {
        tin[v] = timer++;
        if (p != -1) {
            up[v][0] = p;
            for (int i = 1; i <= L; i++) {
                up[v][i] = up[up[v][i-1]][i-1];
            }
        }
        for (int to : ages[v]) {
            if (to != p) {
                dfs(to, v);
            }
        }
        tout[v] = timer++;
    }

    private static int nextInt() throws IOException{
        st.nextToken();
        return (int) st.nval;
    }

}


import java.util.*;
import java.io.*;
public class b {
public static void main(String[] args) throws IOException
{
    boolean[] sieve = new boolean[1000001];
    Arrays.fill(sieve, true);
    sieve[0]=sieve[1]=false;
    for(int i = 2; i<sieve.length; i++) if(sieve[i]) for(long j = (long)i*i; j<sieve.length; j+=i) sieve[(int)j] = false;
    //Scanner input = new Scanner(new File("input.txt"));
    //PrintWriter out = new PrintWriter(new File("output.txt"));
    PrintWriter out = new PrintWriter(System.out);
    input.init(System.in);
    int n= input.nextInt();
    int[] st = new int[n], en = new int[n];
    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 = input.nextInt()-1, b = input.nextInt()-1;
        st[i] = a;
        en[i] = b;
        adj[a].add(b);
        adj[b].add(a);
    }
    int[] parents = new int[n];
    Arrays.fill(parents,-1);
    parents[0]=-2;
    Queue<Integer> q = new LinkedList<Integer>();
    q.add(0);
    while(!q.isEmpty())
    {
        int at = q.poll();
        for(int i: adj[at])
        {
            if(parents[i]==-1)
            {
                parents[i] = at;
                q.add(i);
            }
        }
    }
    LCT lct = new LCT(n);
    for(int i = 1; i<n; i++)
        lct.link(i,parents[i]);
    int k = input.nextInt();
    for(int i = 0; i<k; i++)
    {
        int a = input.nextInt()-1, b = input.nextInt()-1;
        lct.incToLCA(a, b, 1);
    }
    for(int i = 0; i<n-1; i++)
    {
        int x = (parents[st[i]] == en[i] ? st[i] : en[i]);
        //out.println("X " + x);
        out.print(lct.val(x)+" ");
    }
    out.close();
}
public static long gcd(long a, long b)
{
if(b == 0) return a;
return gcd(b, a%b);
}
public static class LCT
{
    int[] p, l, r, pp, val, prop;
    int NULL;
    LCT(int n)
    {
        val = new int[n+1];     //the value contained in each node
        prop = new int[n+1];    //lazily propagating value change
        Arrays.fill(p=new int[n+1],NULL=n); //make NULL n to avoid array out of bounds errors
        Arrays.fill(l=new int[n+1],NULL); //parent, left, and right refer to aux tree
        Arrays.fill(r=new int[n+1],NULL);
        Arrays.fill(pp=new int[n+1], NULL); //the root of each aux tree has one of these to that preferred path's top member's parent in represented tree
    }
    //increment everything on the simple path from v to w (going through their LCA)
    void incToLCA(int v, int w, int inc)
    {
        incPath(v, inc);
        incPath(w, inc);
        int lca = LCA(v,w);
        incPath(lca,-2*inc);
        //value[lca] += inc; //if you want to include the LCA in your incrementing
    }
    //returns the least common ancestor of two nodes in the represented tree
    int LCA(int v, int w)
    {
        access(v);
        access(w);
        splay(v);
        if(pp[v] == NULL) return v; //they're in the same aux tree, so w's path to the root passed through v -> answer is v
        return pp[v]; //the point at which the w-root path made the v-root path no longer preferred is where the two paths intersect, or pp[v]
    }
    //finds and splays root of v's represented tree
    int findRoot(int v)
    {
        access(v);
        while(l[v] != NULL) v = l[v];
        splay(v);
        return v;
    }
    //return value at v
    int val(int v)
    {
        access(v);
        return val[v];
    }
    //increment each node on v-root path by inc
    void incPath(int v, int inc)
    {
        access(v);
        val[v] += inc;
        prop[l[v]] += inc;
    }
    //w becomes v's parent
    //must be in different aux trees
    void link(int v, int w)
    {
        access(v);
        access(w);
        p[l[v]=w] = v;
    }
    //cuts off v from its parent
    void cut(int v)
    {
        access(v);
        p[l[v]] = NULL;
        l[v] = NULL;
    }
    void access(int v)
    {
        splay(v);
        //get rid of v's preferred child
        if(r[v] != NULL)
        {
            pp[r[v]] = v;
            p[r[v]] = NULL;
            r[v] = NULL;
        }
        //make v-root path preferred
        while(pp[v] != NULL)
        {
            int w = pp[v];
            splay(w);
            if(r[w]!=NULL)
                pp[r[w]] = w;
            p[r[w]] = NULL;
            r[w] = v;
            p[v] = w;
            pp[v] = NULL;
            lift(v);
        }
    }
    //splays vertex v (moves it to top of its aux tree)
    void splay(int v)
    {
        while(p[v] != NULL)
            if(p[p[v]] != NULL && (l[l[p[p[v]]]] == v || r[r[p[p[v]]]] == v)) lift(p[v]);
            else lift(v);
    }
    //lift x by one in its aux tree
    void lift(int x)
    {
        //take care of carry
        int inc = prop[p[x]];
        val[p[x]] += inc;
        prop[l[p[x]]] += inc;
        prop[r[p[x]]] += inc;
        prop[p[x]] = 0;
        val[x] += prop[x];
        prop[l[x]] += prop[x];
        prop[r[x]] += prop[x];
        prop[x] = 0;
        if(p[x] == NULL) return;
        pp[x] = pp[p[x]]; //move parent pointer to x if y is root
        pp[p[x]] = NULL;
        int y = p[x], z = p[y];
        p[p[y]=x] = z;
        if(z != NULL) //adjust grandparent's left/right pointer to point to x
            if(l[z] == y) l[z] = x;
            else r[z] = x;
        if(l[y] == x) //zig (x<p[x])
        {
            if((l[y]=r[x])!=NULL) p[r[x]] = y;
            r[x] = y;
        }
        else //zag (x>p[x])
        {
            if((r[y]=l[x])!=NULL) p[l[x]] = y;
            l[x] = y;
        }
    }
}
public static class input {
    static BufferedReader reader;
    static StringTokenizer tokenizer;

    /** call this method to initialize reader for InputStream */
    static void init(InputStream input) {
        reader = new BufferedReader(
                     new InputStreamReader(input) );
        tokenizer = new StringTokenizer("");
    }

    /** get next word */
    static String next() throws IOException {
        while ( ! tokenizer.hasMoreTokens() ) {
            //TODO add check for eof if necessary
            tokenizer = new StringTokenizer(
                   reader.readLine() );
        }
        return tokenizer.nextToken();
    }

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

    static double nextDouble() throws IOException {
        return Double.parseDouble( next() );
    }
    static long nextLong() throws IOException {
        return Long.parseLong( next() );
    }
}
}


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

public class E
{
   public static void main(String[] args)
   {
      PrintWriter out = new PrintWriter(System.out);
      new E(new FastScanner(), out);
      out.close();
   }

   Graph g;
   int[] left, right, ids, level;
   int cnt;
   void dfs(int i, int p, int d)
   {
      level[i] = d;
      ids[cnt] = i;
      right[i] = left[i] = cnt++;
      for (int j : g.adj[i]) if (j != p)
      {
         dfs(j,i,d+1);
         ids[cnt] = i;
         right[i] = cnt++;
      }
   }

   ArrayList<Integer>[] pending;
   int[] covered;
   BIT bit;

   void go(int i, int p)
   {
      covered[i] = bit.sum(left[i], right[i]);
      if (i < pending.length)
         for (int j : pending[i])
            bit.inc(left[j], 1);
      for (int j : g.adj[i])
         if (j != p)
            go(j, i);
   }

   public E(FastScanner in, PrintWriter out)
   {
      int N = in.nextInt();
      g = new Graph(N*2-1);
      for (int u=1; u<N; u++)
      {
         int i = in.nextInt()-1;
         int j = in.nextInt()-1;
         int k = N+u-1;
         g.add(i,k);
         g.add(j,k);
      }
      left = new int[N*2];
      right = new int[N*2];
      level = new int[N*2];
      ids = new int[g.N*10];
      cnt = 0;
      dfs(0,-1,0);
      //if (true) return;
      IntervalTree it = new IntervalTree(0,cnt);
      bit = new BIT(cnt);
      pending = new ArrayList[N];
      for (int i=0; i<N; i++)
         pending[i] = new ArrayList<Integer>();
      for (int i=0; i<cnt; i++)
         it.add(i,i,level[ids[i]]);
      int Q = in.nextInt();
      while (Q-->0)
      {
         int i = in.nextInt()-1;
         int j = in.nextInt()-1;

         //System.out.printf("left %d %d%n", left[i], left[j]);
         //System.out.printf("right %d %d%n", right[i], right[j]);
         int ii = Math.min(left[i], left[j]);
         int jj = Math.max(right[i], right[j]);
         //System.out.printf("%d %d%n", ii, jj);
         int[] lca = it.minimum(ii,jj);
         //out.printf("lvl=%d id=%d%n", lca[0], ids[lca[1]]+1);
         int lcai = ids[lca[1]];
         pending[lcai].add(i);
         pending[lcai].add(j);
      }

      covered = new int[g.N];
      go(0,-1);

      StringBuilder sb = new StringBuilder();
      for (int u=N; u<g.N; u++)
      {
         sb.append(covered[u]);
         sb.append(' ');
      }
      out.println(sb.toString().trim());
   }
}

class Graph
{
   int N;
   ArrayList<Integer>[] adj;
   public Graph(int n)
   {
      adj = new ArrayList[N=n];
      for (int i=0; i<N; i++)
         adj[i] = new ArrayList<Integer>();
   }

   void add(int i, int j)
   {
      //System.out.printf("%d %d%n", i, j);
      adj[i].add(j);
      adj[j].add(i);
   }
}

class IntervalTree {
	int[] tree,delta,lo,hi,val;
	IntervalTree(int l,int h) { //lowest key, highest key
		int n = h-l+1;
		tree = new int[n*4+1];
		delta = new int[n*4+1];
		lo = new int[n*4+1];
		hi = new int[n*4+1];
		val = new int[n*4+1];
		init(1,l,h);
	}
	void init(int i, int l, int r) {
		lo[i]=l;hi[i]=r;
		if(l==r)
		{
		   val[i] = l;
		   return;
		}
		int m = (l+r-1)/2;
		init(2*i,l,m);
		init(2*i+1,m+1,r);
	}
	void add(int l, int r, int x) {
		add(1,l,r,x);
	}
	void add(int i, int left, int right, int x) {
		if(lo[i] >= left && hi[i] <= right)
			delta[i] += x;
		else if(hi[i] >= left && lo[i] <= right) {
			add(2*i, left, right, x);
			add(2*i+1,left,right,x);

			int leftSide = tree[2*i]+delta[2*i];
			int rightSide = tree[2*i+1]+delta[2*i+1];
			tree[i] = Math.min(leftSide, rightSide);
			if (leftSide < rightSide)
				val[i] = val[2*i];
			else
				val[i] = val[2*i+1];
		}
	}
	int[] minimum(int l, int r) {
		return minimum(1,l,r);
	}
	int[] minimum(int i, int left, int right) {
		if(lo[i] >= left && hi[i] <= right) return new int[]{tree[i]+delta[i],val[i]};
		if(hi[i] < left || lo[i] > right) return new int[]{Integer.MAX_VALUE,0};
		int[] leftVal = minimum(2*i,left,right);
		int[] rightVal = minimum(2*i+1,left,right);
		int r1 = delta[i] + Math.min(leftVal[0],rightVal[0]);
		int r2 = rightVal[1];
		if (leftVal[0] < rightVal[0])
			r2 = leftVal[1];
		leftVal[0] = r1;
		leftVal[1] = r2;
		return leftVal;
	}
}

class BIT {
	int n;
	int[] v;
	BIT(int N) {
		v = new int[n=N];
	}
	int sum(int i, int j)
   {
      return sum(j)-sum(i-1);
   }
   int sum(int x) {
	   	return x<0?0:(v[x]+sum((x&(x+1))-1));
	}
	void inc(int p, int x) {
		for(int i=p; i<n; i|=(i+1)) v[i]+=x;
	}
}

class FastScanner{
   private InputStream stream;
   private byte[] buf = new byte[1024];
   private int curChar;
   private int numChars;

   public FastScanner()
   {
      stream = System.in;
   }

   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++];
   }

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

   boolean isEndline(int c)
   {
      return c=='\n'||c=='\r'||c==-1;
   }

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

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

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

   String next(){
      int c = read();
      while (isSpaceChar(c))
         c = read();
      StringBuilder res = new StringBuilder();
      do{
         res.appendCodePoint(c);
         c = read();
      }while(!isSpaceChar(c));
      return res.toString();
   }

   String nextLine(){
      int c = read();
      while (isEndline(c))
         c = read();
      StringBuilder res = new StringBuilder();
      do{
         res.appendCodePoint(c);
         c = read();
      }while(!isEndline(c));
      return res.toString();
   }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ProblemE {

    static class Edge {
        static int _id = 0;
        int a;
        int b;
        int id;
        Edge(String line) {
            String[] d = line.split(" ");
            id = _id++;
            a = Integer.valueOf(d[0])-1;
            b = Integer.valueOf(d[1])-1;
        }
    }

    static List<Edge>[] graph;
    static int[][] parent;
    static int[] depth;

    static void dfs(int now, int from, int dep) {
        parent[0][now] = from;
        depth[now] = dep;
        for (Edge e : graph[now]) {
            int to = (e.a == now) ? e.b : e.a;
            if (to != from) {
                dfs(to, now, dep+1);
            }
        }
    }

    static void init(int n) {
        int log = 1;
        int nn = n;
        while (nn >= 1) {
            nn /= 2;
            log++;
        }
        parent = new int[log+1][n];
        for (int i = 0 ; i <= log ; i++) {
            Arrays.fill(parent[i], -1);
        }
        depth = new int[n];

        dfs(0, -1, 0);

        for (int k = 0 ; k < log ; k++) {
            for (int v = 0 ; v < n ; v++) {
                if (parent[k][v] < 0) {
                    parent[k+1][v] = -1;
                } else {
                    parent[k+1][v] = parent[k][parent[k][v]];
                }
            }
        }
    }

    static int lca(int u, int v) {
        int loglen = parent.length;
        if (depth[u] > depth[v]) {
            int tmp = u;
            u = v;
            v = tmp;
        }
        for (int k = 0 ; k < loglen ; k++) {
            if (((depth[v] - depth[u]) >> k) % 2 == 1) {
                v = parent[k][v];
            }
        }
        if (u == v) {
            return u;
        }

        for (int k = loglen-1 ; k >= 0 ; k--) {
            if (parent[k][u] != parent[k][v]) {
                u = parent[k][u];
                v = parent[k][v];
            }
        }
        return parent[0][u];
    }

    static int[] value;
    static int[] edgeValue;

    static int dfs2(int now, int from) {
        Edge retedge = null;
        int val = 0;
        for (Edge e : graph[now]) {
            int to = (e.a == now) ? e.b : e.a;
            if (to != from) {
                val += dfs2(to, now);
            } else {
                retedge = e;
            }
        }
        if (retedge != null) {
            val += value[now];
            edgeValue[retedge.id] = val;
        }
        return val;
    }

    public static void main(String[] args) throws IOException {
        BufferedReader s = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter out = new PrintWriter(System.out);

        int n = Integer.valueOf(s.readLine());
        graph = new List[n];
        for (int i = 0 ; i < n ; i++) {
            graph[i] = new ArrayList<Edge>();
        }
        for (int i = 0 ; i < n-1 ; i++) {
            Edge e = new Edge(s.readLine());
            graph[e.a].add(e);
            graph[e.b].add(e);
        }
        init(n);

        int m = Integer.valueOf(s.readLine());
        value = new int[n];
        for (int i = 0 ; i < m ; i++) {
            String[] data = s.readLine().split(" ");
            int from = Integer.valueOf(data[0]) -1;
            int to = Integer.valueOf(data[1]) - 1;
            int lca = lca(from, to);
            value[from]++;
            value[to]++;
            value[lca]-=2;
        }

        edgeValue = new int[n-1];
        dfs2(0, -1);

        StringBuffer answer = new StringBuffer();
        for (int i = 0 ; i < n-1 ; i++) {
            answer.append(" ").append(edgeValue[i]);
        }
        out.println(answer.substring(1));
        out.flush();
    }

    public static void debug(Object... os){
        System.err.println(Arrays.deepToString(os));
    }
}


import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Arrays;
import java.io.BufferedWriter;
import java.util.TreeMap;
import java.util.InputMismatchException;
import java.util.ArrayList;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.math.BigInteger;
import java.io.InputStream;

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

class TaskE {
	public void solve(int testNumber, InputReader in, OutputWriter out) {
        int n = in.nextInt();
        Graph g = new Graph(n);
        int i,j,k;

        TreeMap<Pair<Integer,Integer>, Integer> ei = new TreeMap<Pair<Integer, Integer>, Integer>();
        for(k=1;k<n;++k){
            i = in.nextInt()-1;
            j = in.nextInt()-1;
            g.addBiEdge(new Edge(i,j));
            ei.put(new Pair(i,j), k-1);
            ei.put(new Pair(j,i), k-1);
        }

        Graph.LCAer lt = new Graph.LCAer(g);
        Graph.HeavyLightDecomposition d = new Graph.HeavyLightDecomposition(g);

        int t[][] = new int[d.ways][];
        for(i=0;i<d.ways;++i) t[i] = new int[d.w[i].length+1];

        for(int m = in.nextInt();m>0;--m){
            int a = in.nextInt()-1, b = in.nextInt()-1;
            int l = lt.lca(a,b);

            int c[];
            if(a!=l){
                int x = lt.nextDownTo(l,a);
                c = d.query(a,x);
                for(i=0;i<c.length;i+=3){
                    t[c[i]][c[i+1]]++;
                    t[c[i]][c[i+2]+1]--;
                }
            }
            if(b!=l){
                int x = lt.nextDownTo(l,b);
                c = d.query(b,x);
                for(i=0;i<c.length;i+=3){
                    t[c[i]][c[i+1]]++;
                    t[c[i]][c[i+2]+1]--;
                }
            }
        }

        for(i=0;i<d.ways;++i){
            for(j=1;j<t[i].length;++j) t[i][j]+=t[i][j-1];
        }

        int ans[] = new int[n-1];

        for(i=0;i<n;++i) if(lt.nthParent(i,1)!=-1){
            j = ei.get(new Pair(i,lt.nthParent(i,1)));
            ans[j] = t[d.wi[i]][d.wj[i]];
        }

        for(int a : ans) out.write(a,' ');
	}
}

class InputReader{
    private InputStream in;
    private byte buffer[] = new byte[1<<11];
    private int cur;
    private int end;

    public InputReader(InputStream stream){
        in = stream;
    }

    public int read(){
        if(end<0) throw new InputMismatchException();
        if(cur>=end){
            cur = 0;
            try{
                end = in.read(buffer);
            }catch(IOException e){
                throw new InputMismatchException();
            }
            if(end<=0) return -1;
        }
        return buffer[cur++];
    }

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

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

    }

class OutputWriter{
    private PrintWriter out;

    public OutputWriter(Writer out){
        this.out = new PrintWriter(out);
    }

    public OutputWriter(OutputStream out){
        this.out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(out)));
    }

    public void close(){
        out.close();
    }

    public void write(Object ... o){
        for(Object x : o) out.print(x);
    }

    }

class Graph{
    public int N;
    public ArrayList<Edge> edges[];

    public Graph(int n){
        N = n;
        edges = new ArrayList[n];
        for(int i=0;i<n;++i) edges[i] = new ArrayList<Edge>();
    }

    public void addBiEdge(Edge ... ex){
        for(Edge e : ex){
            edges[e.from].add(e);
            edges[e.to].add(e.inv());
        }
    }

    public static class LCAer{
        private int p[][];
        private int log;
        private Graph g;
        private int ti[], to[], tm;

        public LCAer(Graph tree){
            int n = tree.N;
            for(log=0; 1<<log<n; ++log);
            ++log;
            p = new int[log][n];
            this.g = tree;
            ti = new int[n];
            to = new int[n];
            tm = 0;
            for(int i=0;i<n;++i) if(ti[i]==0) dfs_p(i, -1);
        }

        private void dfs_p(int v, int par){
            ti[v] = ++tm;
            p[0][v] = par;
            for(int i=1;i<log;++i) p[i][v] = p[i-1][v]==-1 ? -1: p[i-1][p[i-1][v]];
            for(Edge e : g.edges[v]) if(ti[e.to]==0) dfs_p(e.to, v);
            to[v] = ++tm;
        }

        private boolean upper(int v, int u){
            return v==-1 || u!=-1 && ti[v]<ti[u] && to[v]>to[u];
        }

        public int lca(int v, int u){
            if(v==u || upper(v,u)) return v;
            if(upper(u,v)) return u;
            for(int i=log-1;i>=0;--i) if(!upper(p[i][v], u)) v = p[i][v];
            return p[0][v];
        }

        public int nextDownTo(int from, int downto){
            for(int i=log-1;i>=0;--i) if(upper(from, p[i][downto])) downto = p[i][downto];
            return downto;
        }

        public int nthParent(int v, int n){
            if(n >= 1<<log) return -1;
            for(int t=0; n<=1<<t; ++t) if((1<<t&n)!=0) v = p[t][v];
            return v;
        }
    }

    public static class HeavyLightDecomposition{
        private Graph g;
        private int p[], s[];
        int w[][], ways, wi[], wj[];
        private int q[];

        public HeavyLightDecomposition(Graph tree){
            int n = tree.N, i;
            this.g = tree;
            p = new int[n];
            Arrays.fill(p,-1);
            s = new int[n];
            for(i=0;i<n;++i) if(s[i]==0) dfs_ps(i, -1);
            wi = new int[n];
            wj = new int[n];
            ways = 0;
            for(i=0;i<n;++i) if(p[i]==-1) dfs_w(i, 0, -1);
            w = new int[ways][];
            ways = 0;
            for(i=0;i<n;++i){
                boolean h = false;
                for(Edge e : g.edges[i]) if(e.to!=p[i] && s[e.to]>0){ h=true; break; }
                if(!h){
                    w[ways] = new int[s[i]+1];
                    for(int j=i, k=0; k<w[ways].length; j=p[j], ++k){
                        w[ways][k] = j;
                        wi[j] = ways;
                        wj[j] = k;
                    }
                    ++ways;
                }
            }
            q = new int[50*3];
        }

        private void dfs_ps(int v, int par){
            p[v] = par;
            s[v] = 1;
            for(Edge e : g.edges[v]) if(e.to!=par){
                dfs_ps(e.to, v);
                s[v] += s[e.to];
            }
        }

        private void dfs_w(int v, int hc, int par){
            boolean h = false;
            for(Edge e : g.edges[v]) if(e.to!=par){
                if(s[e.to]*2>=s[v]){
                    h = true;
                    dfs_w(e.to, hc+1, v);
                }else dfs_w(e.to, 0, v);
            }
            s[v] = hc;
            if(!h) ++ways;
        }

        public int[] query(int from, int to){
            int m = 0;
            for(;;){
                int fi = wi[from];
                int end = w[fi][w[fi].length-1];
                if(fi==wi[to]) end = to;
                q[m++] = fi;
                q[m++] = wj[from];
                q[m++] = wj[end];
                if(end==to) break;
                from = p[end];
            }
            return Arrays.copyOf(q, m);
        }
    }

}

class Pair<X,Y> implements Comparable<Pair>{

    public X first;
    public Y second;

    public Pair(X _first, Y _second){
        first = _first;
        second = _second;
    }

    public int compareTo(Pair o){
        int cmp1 = ((Comparable)first).compareTo(o.first);
        int cmp2 = ((Comparable)second).compareTo(o.second);
        return cmp1==0 ? cmp2 : cmp1;
    }
}

class Edge{
    public int from, to;

    public Edge(int _form, int _to){
        from =  _form;
        to = _to;
    }

    public Edge(){}

    public Edge inv(){
        return new Edge(to, from);
    }

    }


import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Arrays;
import java.io.BufferedWriter;
import java.util.InputMismatchException;
import java.util.ArrayList;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.math.BigInteger;
import java.io.InputStream;

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

class TaskE {
	public void solve(int testNumber, InputReader in, OutputWriter out) {
        int n = in.nextInt();
        Graph g = new Graph(n);
        int i,j,k;

        int ei[][] = new int[n][2];
        for(k=1;k<n;++k){
            i = in.nextInt()-1;
            j = in.nextInt()-1;
            g.addBiEdge(new Edge(i,j));
            ei[k-1][0] = i;
            ei[k-1][1] = j;
        }

        Graph.LCAer lt = new Graph.LCAer(g);
        Graph.HeavyLightDecomposition d = new Graph.HeavyLightDecomposition(g);

        int t[][] = new int[d.ways][];
        for(i=0;i<d.ways;++i) t[i] = new int[d.w[i].length+1];

        for(int m = in.nextInt();m>0;--m){
            int a = in.nextInt()-1, b = in.nextInt()-1;
            int l = lt.lca(a,b);

            int c[];
            if(a!=l){
                int x = lt.nextDownTo(l,a);
                c = d.query(a,x);
                for(i=0;i<c.length;i+=3){
                    t[c[i]][c[i+1]]++;
                    t[c[i]][c[i+2]+1]--;
                }
            }
            if(b!=l){
                int x = lt.nextDownTo(l,b);
                c = d.query(b,x);
                for(i=0;i<c.length;i+=3){
                    t[c[i]][c[i+1]]++;
                    t[c[i]][c[i+2]+1]--;
                }
            }
        }

        for(i=0;i<d.ways;++i){
            for(j=1;j<t[i].length;++j) t[i][j]+=t[i][j-1];
        }

        for(k=0;k<n-1;++k){
            i = ei[k][0];
            if(lt.nthParent(i,1)!=ei[k][1]) i = ei[k][1];
            out.write(t[d.wi[i]][d.wj[i]],' ');
        }
	}
}

class InputReader{
    private InputStream in;
    private byte buffer[] = new byte[1<<11];
    private int cur;
    private int end;

    public InputReader(InputStream stream){
        in = stream;
    }

    public int read(){
        if(end<0) throw new InputMismatchException();
        if(cur>=end){
            cur = 0;
            try{
                end = in.read(buffer);
            }catch(IOException e){
                throw new InputMismatchException();
            }
            if(end<=0) return -1;
        }
        return buffer[cur++];
    }

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

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

    }

class OutputWriter{
    private PrintWriter out;

    public OutputWriter(Writer out){
        this.out = new PrintWriter(out);
    }

    public OutputWriter(OutputStream out){
        this.out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(out)));
    }

    public void close(){
        out.close();
    }

    public void write(Object ... o){
        for(Object x : o) out.print(x);
    }

    }

class Graph{
    public int N;
    public ArrayList<Edge> edges[];

    public Graph(int n){
        N = n;
        edges = new ArrayList[n];
        for(int i=0;i<n;++i) edges[i] = new ArrayList<Edge>();
    }

    public void addBiEdge(Edge ... ex){
        for(Edge e : ex){
            edges[e.from].add(e);
            edges[e.to].add(e.inv());
        }
    }

    public static class LCAer{
        private int p[][];
        private int log;
        private Graph g;
        private int ti[], to[], tm;

        public LCAer(Graph tree){
            int n = tree.N;
            for(log=0; 1<<log<n; ++log);
            ++log;
            p = new int[log][n];
            this.g = tree;
            ti = new int[n];
            to = new int[n];
            tm = 0;
            for(int i=0;i<n;++i) if(ti[i]==0) dfs_p(i, -1);
        }

        private void dfs_p(int v, int par){
            ti[v] = ++tm;
            p[0][v] = par;
            for(int i=1;i<log;++i) p[i][v] = p[i-1][v]==-1 ? -1: p[i-1][p[i-1][v]];
            for(Edge e : g.edges[v]) if(ti[e.to]==0) dfs_p(e.to, v);
            to[v] = ++tm;
        }

        private boolean upper(int v, int u){
            return v==-1 || u!=-1 && ti[v]<ti[u] && to[v]>to[u];
        }

        public int lca(int v, int u){
            if(v==u || upper(v,u)) return v;
            if(upper(u,v)) return u;
            for(int i=log-1;i>=0;--i) if(!upper(p[i][v], u)) v = p[i][v];
            return p[0][v];
        }

        public int nextDownTo(int from, int downto){
            for(int i=log-1;i>=0;--i) if(upper(from, p[i][downto])) downto = p[i][downto];
            return downto;
        }

        public int nthParent(int v, int n){
            if(n >= 1<<log) return -1;
            for(int t=0; n<=1<<t; ++t) if((1<<t&n)!=0) v = p[t][v];
            return v;
        }
    }

    public static class HeavyLightDecomposition{
        private Graph g;
        private int p[], s[];
        int w[][], ways, wi[], wj[];
        private int q[];

        public HeavyLightDecomposition(Graph tree){
            int n = tree.N, i;
            this.g = tree;
            p = new int[n];
            Arrays.fill(p,-1);
            s = new int[n];
            for(i=0;i<n;++i) if(s[i]==0) dfs_ps(i, -1);
            wi = new int[n];
            wj = new int[n];
            ways = 0;
            for(i=0;i<n;++i) if(p[i]==-1) dfs_w(i, 0, -1);
            w = new int[ways][];
            ways = 0;
            for(i=0;i<n;++i){
                boolean h = false;
                for(Edge e : g.edges[i]) if(e.to!=p[i] && s[e.to]>0){ h=true; break; }
                if(!h){
                    w[ways] = new int[s[i]+1];
                    for(int j=i, k=0; k<w[ways].length; j=p[j], ++k){
                        w[ways][k] = j;
                        wi[j] = ways;
                        wj[j] = k;
                    }
                    ++ways;
                }
            }
            q = new int[50*3];
        }

        private void dfs_ps(int v, int par){
            p[v] = par;
            s[v] = 1;
            for(Edge e : g.edges[v]) if(e.to!=par){
                dfs_ps(e.to, v);
                s[v] += s[e.to];
            }
        }

        private void dfs_w(int v, int hc, int par){
            boolean h = false;
            for(Edge e : g.edges[v]) if(e.to!=par){
                if(s[e.to]*2>=s[v]){
                    h = true;
                    dfs_w(e.to, hc+1, v);
                }else dfs_w(e.to, 0, v);
            }
            s[v] = hc;
            if(!h) ++ways;
        }

        public int[] query(int from, int to){
            int m = 0;
            for(;;){
                int fi = wi[from];
                int end = w[fi][w[fi].length-1];
                if(fi==wi[to]) end = to;
                q[m++] = fi;
                q[m++] = wj[from];
                q[m++] = wj[end];
                if(end==to) break;
                from = p[end];
            }
            return Arrays.copyOf(q, m);
        }
    }

}

class Edge{
    public int from, to;

    public Edge(int _form, int _to){
        from =  _form;
        to = _to;
    }

    public Edge(){}

    public Edge inv(){
        return new Edge(to, from);
    }

    }


import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Arrays;
import java.io.BufferedWriter;
import java.util.TreeMap;
import java.util.InputMismatchException;
import java.util.ArrayList;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Random;
import java.util.TreeSet;
import java.io.Writer;
import java.math.BigInteger;
import java.io.InputStream;

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

class TaskE {
	public void solve(int testNumber, InputReader in, OutputWriter out) {
        int n = in.nextInt();
        Graph g = new Graph(n);
        int i,j,k;

        TreeMap<Pair<Integer,Integer>, Integer> ei = new TreeMap<Pair<Integer, Integer>, Integer>();
        for(k=1;k<n;++k){
            i = in.nextInt()-1;
            j = in.nextInt()-1;
            g.addBiEdge(new Edge(i,j));
            ei.put(new Pair(i,j), k-1);
            ei.put(new Pair(j,i), k-1);
        }

        Graph.LCAer lt = new Graph.LCAer(g);
        Graph.HeavyLightDecomposition d = new Graph.HeavyLightDecomposition(g);

        DataStruct.SegmentTreeSegAdd t[] = new DataStruct.SegmentTreeSegAdd[d.ways];
        for(i=0;i<d.ways;++i) t[i] = new DataStruct.SegmentTreeSegAdd(d.w[i].length);

        for(int m = in.nextInt();m>0;--m){
            int a = in.nextInt()-1, b = in.nextInt()-1;
            int l = lt.lca(a,b);

            int c[];
            if(a!=l){
                int x = lt.nextDownTo(l,a);
                c = d.query(a,x);
                for(i=0;i<c.length;i+=3){
                    t[c[i]].addRange(c[i+1],c[i+2],1);
                }
            }
            if(b!=l){
                int x = lt.nextDownTo(l,b);
                c = d.query(b,x);
                for(i=0;i<c.length;i+=3){
                    t[c[i]].addRange(c[i+1],c[i+2],1);
                }
            }
        }

        int ans[] = new int[n-1];

        for(i=0;i<n;++i) if(lt.nthParent(i,1)!=-1){
            j = ei.get(new Pair(i,lt.nthParent(i,1)));
            ans[j] = t[d.wi[i]].getItem(d.wj[i]);
        }

        for(int a : ans) out.write(a,' ');
	}
}

class InputReader{
    private InputStream in;
    private byte buffer[] = new byte[1<<11];
    private int cur;
    private int end;

    public InputReader(InputStream stream){
        in = stream;
    }

    public int read(){
        if(end<0) throw new InputMismatchException();
        if(cur>=end){
            cur = 0;
            try{
                end = in.read(buffer);
            }catch(IOException e){
                throw new InputMismatchException();
            }
            if(end<=0) return -1;
        }
        return buffer[cur++];
    }

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

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

    }

class OutputWriter{
    private PrintWriter out;

    public OutputWriter(Writer out){
        this.out = new PrintWriter(out);
    }

    public OutputWriter(OutputStream out){
        this.out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(out)));
    }

    public void close(){
        out.close();
    }

    public void write(Object ... o){
        for(Object x : o) out.print(x);
    }

    }

class Graph{
    public int N;
    public ArrayList<Edge> edges[];

    public Graph(int n){
        N = n;
        edges = new ArrayList[n];
        for(int i=0;i<n;++i) edges[i] = new ArrayList<Edge>();
    }

    public void addBiEdge(Edge ... ex){
        for(Edge e : ex){
            edges[e.from].add(e);
            edges[e.to].add(e.inv());
        }
    }

    public static class LCAer{
        private int p[][];
        private int log;
        private Graph g;
        private int ti[], to[], tm;

        public LCAer(Graph tree){
            int n = tree.N;
            for(log=0; 1<<log<n; ++log);
            ++log;
            p = new int[log][n];
            this.g = tree;
            ti = new int[n];
            to = new int[n];
            tm = 0;
            for(int i=0;i<n;++i) if(ti[i]==0) dfs_p(i, -1);
        }

        private void dfs_p(int v, int par){
            ti[v] = ++tm;
            p[0][v] = par;
            for(int i=1;i<log;++i) p[i][v] = p[i-1][v]==-1 ? -1: p[i-1][p[i-1][v]];
            for(Edge e : g.edges[v]) if(ti[e.to]==0) dfs_p(e.to, v);
            to[v] = ++tm;
        }

        private boolean upper(int v, int u){
            return v==-1 || u!=-1 && ti[v]<ti[u] && to[v]>to[u];
        }

        public int lca(int v, int u){
            if(v==u || upper(v,u)) return v;
            if(upper(u,v)) return u;
            for(int i=log-1;i>=0;--i) if(!upper(p[i][v], u)) v = p[i][v];
            return p[0][v];
        }

        public int nextDownTo(int from, int downto){
            for(int i=log-1;i>=0;--i) if(upper(from, p[i][downto])) downto = p[i][downto];
            return downto;
        }

        public int nthParent(int v, int n){
            if(n >= 1<<log) return -1;
            for(int t=0; n<=1<<t; ++t) if((1<<t&n)!=0) v = p[t][v];
            return v;
        }
    }

    public static class HeavyLightDecomposition{
        private Graph g;
        private int p[], s[];
        int w[][], ways, wi[], wj[];
        private int q[];

        public HeavyLightDecomposition(Graph tree){
            int n = tree.N, i;
            this.g = tree;
            p = new int[n];
            Arrays.fill(p,-1);
            s = new int[n];
            for(i=0;i<n;++i) if(s[i]==0) dfs_ps(i, -1);
            wi = new int[n];
            wj = new int[n];
            ways = 0;
            for(i=0;i<n;++i) if(p[i]==-1) dfs_w(i, 0, -1);
            w = new int[ways][];
            ways = 0;
            for(i=0;i<n;++i){
                boolean h = false;
                for(Edge e : g.edges[i]) if(e.to!=p[i] && s[e.to]>0){ h=true; break; }
                if(!h){
                    w[ways] = new int[s[i]+1];
                    for(int j=i, k=0; k<w[ways].length; j=p[j], ++k){
                        w[ways][k] = j;
                        wi[j] = ways;
                        wj[j] = k;
                    }
                    ++ways;
                }
            }
            q = new int[50*3];
        }

        private void dfs_ps(int v, int par){
            p[v] = par;
            s[v] = 1;
            for(Edge e : g.edges[v]) if(e.to!=par){
                dfs_ps(e.to, v);
                s[v] += s[e.to];
            }
        }

        private void dfs_w(int v, int hc, int par){
            boolean h = false;
            for(Edge e : g.edges[v]) if(e.to!=par){
                if(s[e.to]*2>=s[v]){
                    h = true;
                    dfs_w(e.to, hc+1, v);
                }else dfs_w(e.to, 0, v);
            }
            s[v] = hc;
            if(!h) ++ways;
        }

        public int[] query(int from, int to){
            int m = 0;
            for(;;){
                int fi = wi[from];
                int end = w[fi][w[fi].length-1];
                if(fi==wi[to]) end = to;
                q[m++] = fi;
                q[m++] = wj[from];
                q[m++] = wj[end];
                if(end==to) break;
                from = p[end];
            }
            return Arrays.copyOf(q, m);
        }
    }

}

class Pair<X,Y> implements Comparable<Pair>{

    public X first;
    public Y second;

    public Pair(X _first, Y _second){
        first = _first;
        second = _second;
    }

    public int compareTo(Pair o){
        int cmp1 = ((Comparable)first).compareTo(o.first);
        int cmp2 = ((Comparable)second).compareTo(o.second);
        return cmp1==0 ? cmp2 : cmp1;
    }
}

class Edge{
    public int from, to;

    public Edge(int _form, int _to){
        from =  _form;
        to = _to;
    }

    public Edge(){}

    public Edge inv(){
        return new Edge(to, from);
    }

    }

class DataStruct {

    public static class SegmentTreeSegAdd{
        private int t[];
        int d;

        public SegmentTreeSegAdd(int n){
            for(d=1; d<n; d<<=1);
            t = new int[d<<1];
        }

        public SegmentTreeSegAdd(int[] array){
            int n = array.length, i;
            for(d=1; d<n; d<<=1);
            t = new int[d<<1];
            for(i=d; i<n+d; ++i) t[i] = array[i-d];
        }

        public void addRange(int left, int right, int value){
            for(int i=left+d, j=right+d; i<=j;){
                int k = Math.min(i&-i, Integer.highestOneBit(j-i+1));
                t[i/k] += value;
                i+=k;
            }
        }

        public int getItem(int index){
            int i, res = 0;
            for(i=index+d; i>0; i>>=1) res += t[i];
            return res;
        }
    }

    }


import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Arrays;
import java.io.BufferedWriter;
import java.util.TreeMap;
import java.util.InputMismatchException;
import java.util.ArrayList;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Random;
import java.util.TreeSet;
import java.io.Writer;
import java.math.BigInteger;
import java.io.InputStream;

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

class TaskE {
	public void solve(int testNumber, InputReader in, OutputWriter out) {
        int n = in.nextInt();
        Graph g = new Graph(n);
        int i,j,k;

        TreeMap<Pair<Integer,Integer>, Integer> ei = new TreeMap<Pair<Integer, Integer>, Integer>();
        for(k=1;k<n;++k){
            i = in.nextInt()-1;
            j = in.nextInt()-1;
            g.addBiEdge(new Edge(i,j));
            ei.put(new Pair(i,j), k-1);
            ei.put(new Pair(j,i), k-1);
        }

        Graph.LCAer lt = new Graph.LCAer(g);
        Graph.HeavyLightDecomposition d = new Graph.HeavyLightDecomposition(g);

        DataStruct.SegmentTreeSegAdd t[] = new DataStruct.SegmentTreeSegAdd[d.ways];
        for(i=0;i<d.ways;++i) t[i] = new DataStruct.SegmentTreeSegAdd(d.w[i].length);

        for(int m = in.nextInt();m>0;--m){
            int a = in.nextInt()-1, b = in.nextInt()-1;
            int l = lt.lca(a,b);

            int c[];
            if(a!=l){
                int x = lt.nextDownTo(l,a);
                c = d.query(a,x);
                for(i=0;i<c.length;i+=3){
                    t[c[i]].addRange(c[i+1],c[i+2],1);
                }
            }
            if(b!=l){
                int x = lt.nextDownTo(l,b);
                c = d.query(b,x);
                for(i=0;i<c.length;i+=3){
                    t[c[i]].addRange(c[i+1],c[i+2],1);
                }
            }
        }

        int ans[] = new int[n-1];

        for(i=0;i<n;++i) if(lt.nthParent(i,1)!=-1){
            j = ei.get(new Pair(i,lt.nthParent(i,1)));
            ans[j] = t[d.wi[i]].getItem(d.wj[i]);
        }

        for(int a : ans) out.write(a,' ');
	}
}

class InputReader{
    private InputStream in;
    private byte buffer[] = new byte[1<<11];
    private int cur;
    private int end;

    public InputReader(InputStream stream){
        in = stream;
    }

    public int read(){
        if(end<0) throw new InputMismatchException();
        if(cur>=end){
            cur = 0;
            try{
                end = in.read(buffer);
            }catch(IOException e){
                throw new InputMismatchException();
            }
            if(end<=0) return -1;
        }
        return buffer[cur++];
    }

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

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

    }

class OutputWriter{
    private PrintWriter out;

    public OutputWriter(Writer out){
        this.out = new PrintWriter(out);
    }

    public OutputWriter(OutputStream out){
        this.out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(out)));
    }

    public void close(){
        out.close();
    }

    public void write(Object ... o){
        for(Object x : o) out.print(x);
    }

    }

class Graph{
    public int N;
    public ArrayList<Edge> edges[];

    public Graph(int n){
        N = n;
        edges = new ArrayList[n];
        for(int i=0;i<n;++i) edges[i] = new ArrayList<Edge>();
    }

    public void addBiEdge(Edge ... ex){
        for(Edge e : ex){
            edges[e.from].add(e);
            edges[e.to].add(e.inv());
        }
    }

    public static class LCAer{
        private int p[][];
        private int log;
        private Graph g;
        private int ti[], to[], tm;

        public LCAer(Graph tree){
            int n = tree.N;
            for(log=0; 1<<log<n; ++log);
            ++log;
            p = new int[log][n];
            this.g = tree;
            ti = new int[n];
            to = new int[n];
            tm = 0;
            for(int i=0;i<n;++i) if(ti[i]==0) dfs_p(i, -1);
        }

        private void dfs_p(int v, int par){
            ti[v] = ++tm;
            p[0][v] = par;
            for(int i=1;i<log;++i) p[i][v] = p[i-1][v]==-1 ? -1: p[i-1][p[i-1][v]];
            for(Edge e : g.edges[v]) if(ti[e.to]==0) dfs_p(e.to, v);
            to[v] = ++tm;
        }

        private boolean upper(int v, int u){
            return v==-1 || u!=-1 && ti[v]<ti[u] && to[v]>to[u];
        }

        public int lca(int v, int u){
            if(v==u || upper(v,u)) return v;
            if(upper(u,v)) return u;
            for(int i=log-1;i>=0;--i) if(!upper(p[i][v], u)) v = p[i][v];
            return p[0][v];
        }

        public int nextDownTo(int from, int downto){
            for(int i=log-1;i>=0;--i) if(upper(from, p[i][downto])) downto = p[i][downto];
            return downto;
        }

        public int nthParent(int v, int n){
            if(n >= 1<<log) return -1;
            for(int t=0; n<=1<<t; ++t) if((1<<t&n)!=0) v = p[t][v];
            return v;
        }
    }

    public static class HeavyLightDecomposition{
        private Graph g;
        private int p[], s[];
        int w[][], ways, wi[], wj[];
        private int q[];

        public HeavyLightDecomposition(Graph tree){
            int n = tree.N, i;
            this.g = tree;
            p = new int[n];
            Arrays.fill(p,-1);
            s = new int[n];
            for(i=0;i<n;++i) if(s[i]==0) dfs_ps(i, -1);
            wi = new int[n];
            wj = new int[n];
            ways = 0;
            for(i=0;i<n;++i) if(p[i]==-1) dfs_w(i, 0, -1);
            w = new int[ways][];
            ways = 0;
            for(i=0;i<n;++i){
                boolean h = false;
                for(Edge e : g.edges[i]) if(e.to!=p[i] && s[e.to]>0){ h=true; break; }
                if(!h){
                    w[ways] = new int[s[i]+1];
                    for(int j=i, k=0; k<w[ways].length; j=p[j], ++k){
                        w[ways][k] = j;
                        wi[j] = ways;
                        wj[j] = k;
                    }
                    ++ways;
                }
            }
            q = new int[50*3];
        }

        private void dfs_ps(int v, int par){
            p[v] = par;
            s[v] = 1;
            for(Edge e : g.edges[v]) if(e.to!=par){
                dfs_ps(e.to, v);
                s[v] += s[e.to];
            }
        }

        private void dfs_w(int v, int hc, int par){
            boolean h = false;
            for(Edge e : g.edges[v]) if(e.to!=par){
                if(s[e.to]*2>=s[v]){
                    h = true;
                    dfs_w(e.to, hc+1, v);
                }else dfs_w(e.to, 0, v);
            }
            s[v] = hc;
            if(!h) ++ways;
        }

        public int[] query(int from, int to){
            int m = 0;
            for(;;){
                int fi = wi[from];
                int end = w[fi][w[fi].length-1];
                if(fi==wi[to]) end = to;
                q[m++] = fi;
                q[m++] = wj[from];
                q[m++] = wj[end];
                if(end==to) break;
                from = p[end];
            }
            return Arrays.copyOf(q, m);
        }
    }

}

class Pair<X,Y> implements Comparable<Pair>{

    public X first;
    public Y second;

    public Pair(X _first, Y _second){
        first = _first;
        second = _second;
    }

    public int compareTo(Pair o){
        int cmp1 = ((Comparable)first).compareTo(o.first);
        int cmp2 = ((Comparable)second).compareTo(o.second);
        return cmp1==0 ? cmp2 : cmp1;
    }
}

class Edge{
    public int from, to;

    public Edge(int _form, int _to){
        from =  _form;
        to = _to;
    }

    public Edge(){}

    public Edge inv(){
        return new Edge(to, from);
    }

    }

class DataStruct {

    public static class SegmentTreeSegAdd{
        private int t[];
        int d;

        public SegmentTreeSegAdd(int n){
            for(d=1; d<n; d<<=1);
            t = new int[d<<1];
        }

        public SegmentTreeSegAdd(int[] array){
            int n = array.length, i;
            for(d=1; d<n; d<<=1);
            t = new int[d<<1];
            for(i=d; i<n+d; ++i) t[i] = array[i-d];
        }

        public void addRange(int left, int right, int value){
            for(int i=left+d; i<=right+d;){
                int k = Math.min(i&-i, Integer.highestOneBit(i));
                t[i/k] += value;
                i+=k;
            }
        }

        public int getItem(int index){
            int i, res = 0;
            for(i=index+d; i>0; i>>=1) res += t[i];
            return res;
        }
    }

    }


import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Arrays;
import java.io.BufferedWriter;
import java.util.TreeMap;
import java.util.InputMismatchException;
import java.util.ArrayList;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Random;
import java.util.TreeSet;
import java.io.Writer;
import java.math.BigInteger;
import java.io.InputStream;

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

class TaskE {
	public void solve(int testNumber, InputReader in, OutputWriter out) {
        int n = in.nextInt();
        Graph g = new Graph(n);
        int i,j,k;

        int ei[][] = new int[n][2];
        for(k=1;k<n;++k){
            i = in.nextInt()-1;
            j = in.nextInt()-1;
            g.addBiEdge(new Edge(i,j));
            ei[k-1][0] = i;
            ei[k-1][1] = j;
        }

        Graph.LCAer lt = new Graph.LCAer(g);
        Graph.HeavyLightDecomposition d = new Graph.HeavyLightDecomposition(g);

        DataStruct.SegmentTreeSegAdd t[] = new DataStruct.SegmentTreeSegAdd[d.ways];
        for(i=0;i<d.ways;++i) t[i] = new DataStruct.SegmentTreeSegAdd(d.w[i].length);

        for(int m = in.nextInt();m>0;--m){
            int a = in.nextInt()-1, b = in.nextInt()-1;
            int l = lt.lca(a,b);

            int c[];
            if(a!=l){
                int x = lt.nextDownTo(l,a);
                c = d.query(a,x);
                for(i=0;i<c.length;i+=3){
                    t[c[i]].addRange(c[i+1],c[i+2],1);
                }
            }
            if(b!=l){
                int x = lt.nextDownTo(l,b);
                c = d.query(b,x);
                for(i=0;i<c.length;i+=3){
                    t[c[i]].addRange(c[i+1],c[i+2],1);
                }
            }
        }

        for(k=0;k<n-1;++k){
            i = ei[k][0];
            if(lt.nthParent(i,1)!=ei[k][1]) i = ei[k][1];
            out.write(t[d.wi[i]].getItem(d.wj[i]),' ');
        }
	}
}

class InputReader{
    private InputStream in;
    private byte buffer[] = new byte[1<<11];
    private int cur;
    private int end;

    public InputReader(InputStream stream){
        in = stream;
    }

    public int read(){
        if(end<0) throw new InputMismatchException();
        if(cur>=end){
            cur = 0;
            try{
                end = in.read(buffer);
            }catch(IOException e){
                throw new InputMismatchException();
            }
            if(end<=0) return -1;
        }
        return buffer[cur++];
    }

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

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

    }

class OutputWriter{
    private PrintWriter out;

    public OutputWriter(Writer out){
        this.out = new PrintWriter(out);
    }

    public OutputWriter(OutputStream out){
        this.out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(out)));
    }

    public void close(){
        out.close();
    }

    public void write(Object ... o){
        for(Object x : o) out.print(x);
    }

    }

class Graph{
    public int N;
    public ArrayList<Edge> edges[];

    public Graph(int n){
        N = n;
        edges = new ArrayList[n];
        for(int i=0;i<n;++i) edges[i] = new ArrayList<Edge>();
    }

    public void addBiEdge(Edge ... ex){
        for(Edge e : ex){
            edges[e.from].add(e);
            edges[e.to].add(e.inv());
        }
    }

    public static class LCAer{
        private int p[][];
        private int log;
        private Graph g;
        private int ti[], to[], tm;

        public LCAer(Graph tree){
            int n = tree.N;
            for(log=0; 1<<log<n; ++log);
            ++log;
            p = new int[log][n];
            this.g = tree;
            ti = new int[n];
            to = new int[n];
            tm = 0;
            for(int i=0;i<n;++i) if(ti[i]==0) dfs_p(i, -1);
        }

        private void dfs_p(int v, int par){
            ti[v] = ++tm;
            p[0][v] = par;
            for(int i=1;i<log;++i) p[i][v] = p[i-1][v]==-1 ? -1: p[i-1][p[i-1][v]];
            for(Edge e : g.edges[v]) if(ti[e.to]==0) dfs_p(e.to, v);
            to[v] = ++tm;
        }

        private boolean upper(int v, int u){
            return v==-1 || u!=-1 && ti[v]<ti[u] && to[v]>to[u];
        }

        public int lca(int v, int u){
            if(v==u || upper(v,u)) return v;
            if(upper(u,v)) return u;
            for(int i=log-1;i>=0;--i) if(!upper(p[i][v], u)) v = p[i][v];
            return p[0][v];
        }

        public int nextDownTo(int from, int downto){
            for(int i=log-1;i>=0;--i) if(upper(from, p[i][downto])) downto = p[i][downto];
            return downto;
        }

        public int nthParent(int v, int n){
            if(n >= 1<<log) return -1;
            for(int t=0; n<=1<<t; ++t) if((1<<t&n)!=0) v = p[t][v];
            return v;
        }
    }

    public static class HeavyLightDecomposition{
        private Graph g;
        private int p[], s[];
        int w[][], ways, wi[], wj[];
        private int q[];

        public HeavyLightDecomposition(Graph tree){
            int n = tree.N, i;
            this.g = tree;
            p = new int[n];
            Arrays.fill(p,-1);
            s = new int[n];
            for(i=0;i<n;++i) if(s[i]==0) dfs_ps(i, -1);
            wi = new int[n];
            wj = new int[n];
            ways = 0;
            for(i=0;i<n;++i) if(p[i]==-1) dfs_w(i, 0, -1);
            w = new int[ways][];
            ways = 0;
            for(i=0;i<n;++i){
                boolean h = false;
                for(Edge e : g.edges[i]) if(e.to!=p[i] && s[e.to]>0){ h=true; break; }
                if(!h){
                    w[ways] = new int[s[i]+1];
                    for(int j=i, k=0; k<w[ways].length; j=p[j], ++k){
                        w[ways][k] = j;
                        wi[j] = ways;
                        wj[j] = k;
                    }
                    ++ways;
                }
            }
            q = new int[50*3];
        }

        private void dfs_ps(int v, int par){
            p[v] = par;
            s[v] = 1;
            for(Edge e : g.edges[v]) if(e.to!=par){
                dfs_ps(e.to, v);
                s[v] += s[e.to];
            }
        }

        private void dfs_w(int v, int hc, int par){
            boolean h = false;
            for(Edge e : g.edges[v]) if(e.to!=par){
                if(s[e.to]*2>=s[v]){
                    h = true;
                    dfs_w(e.to, hc+1, v);
                }else dfs_w(e.to, 0, v);
            }
            s[v] = hc;
            if(!h) ++ways;
        }

        public int[] query(int from, int to){
            int m = 0;
            for(;;){
                int fi = wi[from];
                int end = w[fi][w[fi].length-1];
                if(fi==wi[to]) end = to;
                q[m++] = fi;
                q[m++] = wj[from];
                q[m++] = wj[end];
                if(end==to) break;
                from = p[end];
            }
            return Arrays.copyOf(q, m);
        }
    }

}

class Edge{
    public int from, to;

    public Edge(int _form, int _to){
        from =  _form;
        to = _to;
    }

    public Edge(){}

    public Edge inv(){
        return new Edge(to, from);
    }

    }

class DataStruct {

    public static class SegmentTreeSegAdd{
        private int t[];
        int d;

        public SegmentTreeSegAdd(int n){
            for(d=1; d<n; d<<=1);
            t = new int[d<<1];
        }

        public SegmentTreeSegAdd(int[] array){
            int n = array.length, i;
            for(d=1; d<n; d<<=1);
            t = new int[d<<1];
            for(i=d; i<n+d; ++i) t[i] = array[i-d];
        }

        public void addRange(int left, int right, int value){
            for(int i=left+d, j=right+d; i<=j;){
                int k = Math.min(i&-i, Integer.highestOneBit(j-i+1));
                t[i/k] += value;
                i+=k;
            }
        }

        public int getItem(int index){
            int i, res = 0;
            for(i=index+d; i>0; i>>=1) res += t[i];
            return res;
        }
    }

    }


import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Arrays;
import java.io.BufferedWriter;
import java.util.TreeMap;
import java.util.InputMismatchException;
import java.util.ArrayList;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Random;
import java.util.TreeSet;
import java.io.Writer;
import java.math.BigInteger;
import java.io.InputStream;

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

class TaskE {
	public void solve(int testNumber, InputReader in, OutputWriter out) {
        int n = in.nextInt();
        Graph g = new Graph(n);
        int i,j,k;

        TreeMap<Pair<Integer,Integer>, Integer> ei = new TreeMap<Pair<Integer, Integer>, Integer>();
        for(k=1;k<n;++k){
            i = in.nextInt()-1;
            j = in.nextInt()-1;
            g.addBiEdge(new Edge(i,j));
            ei.put(new Pair(i,j), k-1);
            ei.put(new Pair(j,i), k-1);
        }

        Graph.LCAer lt = new Graph.LCAer(g);
        Graph.HeavyLightDecomposition d = new Graph.HeavyLightDecomposition(g);

        DataStruct.SegmentTreeSegAdd t[] = new DataStruct.SegmentTreeSegAdd[d.ways];
        for(i=0;i<d.ways;++i) t[i] = new DataStruct.SegmentTreeSegAdd(d.w[i].length);

        for(int m = in.nextInt();m>0;--m){
            int a = in.nextInt()-1, b = in.nextInt()-1;
            int l = lt.lca(a,b);

            int c[];
            if(a!=l){
                int x = lt.nextDownTo(l,a);
                c = d.query(a,x);
                for(i=0;i<c.length;i+=3){
                    t[c[i]].addRange(c[i+1],c[i+2],1);
                }
            }
            if(b!=l){
                int x = lt.nextDownTo(l,b);
                c = d.query(b,x);
                for(i=0;i<c.length;i+=3){
                    t[c[i]].addRange(c[i+1],c[i+2],1);
                }
            }
        }

        int ans[] = new int[n-1];

        for(i=0;i<n;++i) if(lt.nthParent(i,1)!=-1){
            j = ei.get(new Pair(i,lt.nthParent(i,1)));
            ans[j] = t[d.wi[i]].getItem(d.wj[i]);
        }

        for(int a : ans) out.write(a,' ');
	}
}

class InputReader{
    private InputStream in;
    private byte buffer[] = new byte[1<<11];
    private int cur;
    private int end;

    public InputReader(InputStream stream){
        in = stream;
    }

    public int read(){
        if(end<0) throw new InputMismatchException();
        if(cur>=end){
            cur = 0;
            try{
                end = in.read(buffer);
            }catch(IOException e){
                throw new InputMismatchException();
            }
            if(end<=0) return -1;
        }
        return buffer[cur++];
    }

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

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

    }

class OutputWriter{
    private PrintWriter out;

    public OutputWriter(Writer out){
        this.out = new PrintWriter(out);
    }

    public OutputWriter(OutputStream out){
        this.out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(out)));
    }

    public void close(){
        out.close();
    }

    public void write(Object ... o){
        for(Object x : o) out.print(x);
    }

    }

class Graph{
    public int N;
    public ArrayList<Edge> edges[];

    public Graph(int n){
        N = n;
        edges = new ArrayList[n];
        for(int i=0;i<n;++i) edges[i] = new ArrayList<Edge>();
    }

    public void addBiEdge(Edge ... ex){
        for(Edge e : ex){
            edges[e.from].add(e);
            edges[e.to].add(e.inv());
        }
    }

    public static class LCAer{
        private int p[][];
        private int log;
        private Graph g;
        private int ti[], to[], tm;

        public LCAer(Graph tree){
            int n = tree.N;
            for(log=0; 1<<log<n; ++log);
            ++log;
            p = new int[log][n];
            this.g = tree;
            ti = new int[n];
            to = new int[n];
            tm = 0;
            for(int i=0;i<n;++i) if(ti[i]==0) dfs_p(i, -1);
        }

        private void dfs_p(int v, int par){
            ti[v] = ++tm;
            p[0][v] = par;
            for(int i=1;i<log;++i) p[i][v] = p[i-1][v]==-1 ? -1: p[i-1][p[i-1][v]];
            for(Edge e : g.edges[v]) if(ti[e.to]==0) dfs_p(e.to, v);
            to[v] = ++tm;
        }

        private boolean upper(int v, int u){
            return v==-1 || u!=-1 && ti[v]<ti[u] && to[v]>to[u];
        }

        public int lca(int v, int u){
            if(v==u || upper(v,u)) return v;
            if(upper(u,v)) return u;
            for(int i=log-1;i>=0;--i) if(!upper(p[i][v], u)) v = p[i][v];
            return p[0][v];
        }

        public int nextDownTo(int from, int downto){
            for(int i=log-1;i>=0;--i) if(upper(from, p[i][downto])) downto = p[i][downto];
            return downto;
        }

        public int nthParent(int v, int n){
            if(n >= 1<<log) return -1;
            for(int t=0; n<=1<<t; ++t) if((1<<t&n)!=0) v = p[t][v];
            return v;
        }
    }

    public static class HeavyLightDecomposition{
        private Graph g;
        private int p[], s[];
        int w[][], ways, wi[], wj[];
        private int q[];

        public HeavyLightDecomposition(Graph tree){
            int n = tree.N, i;
            this.g = tree;
            p = new int[n];
            Arrays.fill(p,-1);
            s = new int[n];
            for(i=0;i<n;++i) if(s[i]==0) dfs_ps(i, -1);
            wi = new int[n];
            wj = new int[n];
            ways = 0;
            for(i=0;i<n;++i) if(p[i]==-1) dfs_w(i, 0, -1);
            w = new int[ways][];
            ways = 0;
            for(i=0;i<n;++i){
                boolean h = false;
                for(Edge e : g.edges[i]) if(e.to!=p[i] && s[e.to]>0){ h=true; break; }
                if(!h){
                    w[ways] = new int[s[i]+1];
                    for(int j=i, k=0; k<w[ways].length; j=p[j], ++k){
                        w[ways][k] = j;
                        wi[j] = ways;
                        wj[j] = k;
                    }
                    ++ways;
                }
            }
            q = new int[50*3];
        }

        private void dfs_ps(int v, int par){
            p[v] = par;
            s[v] = 1;
            for(Edge e : g.edges[v]) if(e.to!=par){
                dfs_ps(e.to, v);
                s[v] += s[e.to];
            }
        }

        private void dfs_w(int v, int hc, int par){
            boolean h = false;
            for(Edge e : g.edges[v]) if(e.to!=par){
                if(s[e.to]*2>=s[v]){
                    h = true;
                    dfs_w(e.to, hc+1, v);
                }else dfs_w(e.to, 0, v);
            }
            s[v] = hc;
            if(!h) ++ways;
        }

        public int[] query(int from, int to){
            int m = 0;
            for(;;){
                int fi = wi[from];
                int end = w[fi][w[fi].length-1];
                if(fi==wi[to]) end = to;
                q[m++] = fi;
                q[m++] = wj[from];
                q[m++] = wj[end];
                if(end==to) break;
                from = p[end];
            }
            return Arrays.copyOf(q, m);
        }
    }

}

class Pair<X,Y> implements Comparable<Pair>{

    public X first;
    public Y second;

    public Pair(X _first, Y _second){
        first = _first;
        second = _second;
    }

    public int compareTo(Pair o){
        int cmp1 = ((Comparable)first).compareTo(o.first);
        int cmp2 = ((Comparable)second).compareTo(o.second);
        return cmp1==0 ? cmp2 : cmp1;
    }
}

class Edge{
    public int from, to;

    public Edge(int _form, int _to){
        from =  _form;
        to = _to;
    }

    public Edge(){}

    public Edge inv(){
        return new Edge(to, from);
    }

    }

class DataStruct {

    public static class SegmentTreeSegAdd{
        private int t[];
        int d;

        public SegmentTreeSegAdd(int n){
            for(d=1; d<n; d<<=1);
            t = new int[d<<1];
        }

        public SegmentTreeSegAdd(int[] array){
            int n = array.length, i;
            for(d=1; d<n; d<<=1);
            t = new int[d<<1];
            for(i=d; i<n+d; ++i) t[i] = array[i-d];
        }

        private void add(int i, int j, int value, int left, int right, int node){
            if(i==left && j==right){
                t[node] += value;
            }else{
                int middle = (left+right)>>1;
                if(i<=middle) add(i, Math.min(j,middle), value, left, middle, node*2);
                if(j>middle) add(Math.max(i, middle + 1), j, value, middle+1, right, node*2+1);
            }
        }

        public void addRange(int left, int right, int value){
            if(left<=right && 0<=left && right<d)
                add(left, right, value, 0, d-1, 1);
        }

        public int getItem(int index){
            int i, res = 0;
            for(i=index+d; i>0; i>>=1) res += t[i];
            return res;
        }
    }

    }


#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;
const int inf=100010;

typedef long long ll;

const int N = 100010;
struct e{
    int v;
    e* nxt;
}es[N<<1], *fir[N];

map<pair<int,int> ,int> mp;
struct node{
    int ls, rs;
    int l, r;
    int sum,add;

    int mid() { return (l + r) >> 1;  }
}nodes[N<<2];
int n, en, val[N];
int que[N], par[N], dep[N], root[N], seg[N], st[N], ed[N], top[N], sons[N], id[N];

int ln, cnt, tr;

inline void init(){
    en=0;
    memset(fir,0,sizeof(fir));
}
inline void add_e(int u, int v){
    es[en].v = v;
    es[en].nxt = fir[u];
    fir[u] = &es[en++];
}
inline void newNode(int &id, int l, int r){
    nodes[cnt].ls = nodes[cnt].rs = -1;
    nodes[cnt].l = l;
    nodes[cnt].r = r;
    id = cnt++;
}
void build(int &id, int l, int r){
    newNode(id, l, r);
    if(l+1>= r){
        nodes[id].sum=0;
        return ;
    }
    int mid = (l+r)>>1;
    build(nodes[id].ls, l, mid);
    build(nodes[id].rs, mid, r);
    nodes[id].sum=nodes[nodes[id].ls].sum+nodes[nodes[id].rs].sum;
}
void initTree(){
    int l, r, u, v, i;
    e* cur;
    l = r = 0;tr=1;
    que[r++] = tr;
    par[tr] = -1;
    dep[tr] = 0;
    while(l != r){
        u = que[l++];
        for(cur = fir[u]; cur; cur = cur->nxt){
            if((v = cur->v) != par[u]){
                que[r++] = v;
                par[v] = u;
                dep[v] = dep[u]+1;
            }
        }
    }
    for(i = 1; i <= n; i++){
        sons[i] = 1;
        id[i] = -1;
    }
    for(i = r-1; i >= 0; i--){
        u = que[i];
        if(par[u] >= 0){
            sons[par[u]] += sons[u];
        }
    }
    l = r = 0;
    que[r++] = tr;
    ln = cnt = 0;
    while(l != r){
        u = que[l++];
        st[ln] = dep[u];
        top[ln] = u;
        while(u >= 0){
            id[u] = ln;
            ed[ln] = dep[u];
            seg[dep[u]] = u;
            int best;
            for(cur = fir[u], best=-1; cur; cur = cur->nxt){
                if(id[v = cur->v] == -1){
                    if(best == -1 || (best >= 0 && sons[v] > sons[best])){
                        best = v;
                    }
                }
            }
            if(best >= 0){
                for(cur = fir[u]; cur; cur = cur->nxt){
                    if(id[v = cur->v] == -1 && best != v){
                        que[r++] = v;
                    }
                }
            }
            u = best;
        }
        root[ln] = -1;
        build(root[ln], st[ln], ed[ln]);
        ln++;
    }
}
int S;
void down(int id)
{
	if (nodes[id].ls != -1) {
		nodes[nodes[id].ls].add += nodes[id].add;
		nodes[nodes[id].ls].sum += nodes[id].add;
	}
	if (nodes[id].rs != -1) {
		nodes[nodes[id].rs].add += nodes[id].add;
		nodes[nodes[id].rs].sum += nodes[id].add;
	}
	nodes[id].add = 0;
}
void lqry(int &id, int ql, int qr){
    if(id == -1) return ;
    if(ql==qr) return;
    if(ql <= nodes[id].l  && nodes[id].r <= qr){
        S+=nodes[id].sum;
        return ;
    }
    if(nodes[id].l+1 == nodes[id].r){
        S+=nodes[id].sum;
        return ;
    }
    if(nodes[id].add)
       	down(id);
    int mid = (nodes[id].l+nodes[id].r)>>1;
    if(ql < mid){
       lqry(nodes[id].ls, ql, qr);
    }
    if(qr > mid){
       lqry(nodes[id].rs, ql, qr);
    }
}

void update(int id, int x,int y,int val)
{
    if(id == -1) return ;
    if(nodes[id].l+1 == nodes[id].r){
        nodes[id].sum+=val;
        return ;
    }
    if(x <= nodes[id].l  && nodes[id].r <= y){
    	 nodes[id].sum+=val;
    	 nodes[id].add+=val;
    	 return;
    }
    if(nodes[id].add)
    	down(id);
    int mid = (nodes[id].l+nodes[id].r)>>1;
    if(x<mid)
        update(nodes[id].ls, x, y,val);
    if(y>mid)
        update(nodes[id].rs, x, y,val);
    nodes[id].sum=nodes[nodes[id].ls].sum+nodes[nodes[id].rs].sum;
}
void upd(int u, int v,int vv){
    while(id[u] != id[v]){
        if(id[u] > id[v]){
            swap(u, v);
        }
        int b = id[v];
        update(root[b], st[b], dep[v],vv);
        v = par[top[b]];
        if(mp.find(make_pair(top[b],par[top[b]]))!=mp.end())
        	val[mp[make_pair(top[b],par[top[b]])]]+=vv;
        else
        	val[mp[make_pair(par[top[b]],top[b])]]+=vv;
    }
    if(dep[u] > dep[v]){
        swap(u, v);
    }
    update(root[id[u]], dep[u], dep[v],vv);
}
void qry(int u, int v){
    while(id[u] != id[v]){
        if(id[u] > id[v]){
            swap(u, v);
        }
        int b = id[v];
        lqry(root[b], st[b], dep[v]);
        v = par[top[b]];
        if(mp.find(make_pair(top[b],par[top[b]]))!=mp.end()){
        	S+=val[mp[make_pair(top[b],par[top[b]])]];
        	//printf("val[mp[make_pair(top[b],par[top[b]])]]");
        }
        else{
        	S+=val[mp[make_pair(par[top[b]],top[b])]];
        }
    }
    if(dep[u] > dep[v]){
        swap(u, v);
    }
    lqry(root[id[u]], dep[u], dep[v]);
}
struct ee{
	int x,y;
}edge[100010];
int main(){
    int m,x,y,u,v;
    scanf("%d",&n);
    init();
    for(int i=1;i<n;i++){
      scanf("%d%d",&x,&y);
      mp[make_pair(x,y)]=i;
      edge[i].x=x;edge[i].y=y;
      add_e(x,y);
      add_e(y,x);
    }
    initTree();

	scanf("%d", &m);
	for (int i = 0; i < m; i++) {
		scanf("%d%d",&u,&v);
		upd(u, v, 1);
	}
	for(int i=1;i<n;i++){
		S = 0;
		qry(edge[i].x,edge[i].y);
		if(i!=n-1)
			printf("%d ",S);
		else
			printf("%d\n",S);
	}

}


#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;
const int inf=100010;

typedef long long ll;

const int N = 100010;
struct e{
    int v;
    e* nxt;
}es[N<<1], *fir[N];

map<pair<int,int> ,int> mp;
struct node{
    int ls, rs;
    int l, r;
    int sum,add;

    int mid() { return (l + r) >> 1;  }
}nodes[N<<2];
int n, en, val[N];
int que[N], par[N], dep[N], root[N], seg[N], st[N], ed[N], top[N], sons[N], id[N];

int ln, cnt, tr;

inline void init(){
    en=0;
    memset(fir,0,sizeof(fir));
}
inline void add_e(int u, int v){
    es[en].v = v;
    es[en].nxt = fir[u];
    fir[u] = &es[en++];
}
inline void newNode(int &id, int l, int r){
    nodes[cnt].ls = nodes[cnt].rs = -1;
    nodes[cnt].l = l;
    nodes[cnt].r = r;
    nodes[cnt].sum=0;
    nodes[cnt].add=0;
    id = cnt++;
}
void build(int &id, int l, int r){
    newNode(id, l, r);
    if(l+1>= r)
        return ;
    int mid = (l+r)>>1;
    build(nodes[id].ls, l, mid);
    build(nodes[id].rs, mid, r);
}
void initTree(){
    int l, r, u, v, i;
    e* cur;
    l = r = 0;tr=1;
    que[r++] = tr;
    par[tr] = -1;
    dep[tr] = 0;
    while(l != r){
        u = que[l++];
        for(cur = fir[u]; cur; cur = cur->nxt){
            if((v = cur->v) != par[u]){
                que[r++] = v;
                par[v] = u;
                dep[v] = dep[u]+1;
            }
        }
    }
    for(i = 1; i <= n; i++){
        sons[i] = 1;
        id[i] = -1;
    }
    for(i = r-1; i >= 0; i--){
        u = que[i];
        if(par[u] >= 0){
            sons[par[u]] += sons[u];
        }
    }
    l = r = 0;
    que[r++] = tr;
    ln = cnt = 0;
    while(l != r){
        u = que[l++];
        st[ln] = dep[u];
        top[ln] = u;
        while(u >= 0){
            id[u] = ln;
            ed[ln] = dep[u];
            seg[dep[u]] = u;
            int best;
            for(cur = fir[u], best=-1; cur; cur = cur->nxt){
                if(id[v = cur->v] == -1){
                    if(best == -1 || (best >= 0 && sons[v] > sons[best])){
                        best = v;
                    }
                }
            }
            if(best >= 0){
                for(cur = fir[u]; cur; cur = cur->nxt){
                    if(id[v = cur->v] == -1 && best != v){
                        que[r++] = v;
                    }
                }
            }
            u = best;
        }
        root[ln] = -1;
        build(root[ln], st[ln], ed[ln]);
        ln++;
    }
}
int S;
void down(int id)
{
	if (nodes[id].ls != -1) {
		nodes[nodes[id].ls].add += nodes[id].add;
		nodes[nodes[id].ls].sum += nodes[id].add;
	}
	if (nodes[id].rs != -1) {
		nodes[nodes[id].rs].add += nodes[id].add;
		nodes[nodes[id].rs].sum += nodes[id].add;
	}
	nodes[id].add = 0;
}
void lqry(int &id, int ql, int qr){
    if(id == -1) return ;
    if(ql==qr) return;
    if(ql <= nodes[id].l  && nodes[id].r <= qr){
        S+=nodes[id].sum;
        return ;
    }
    if(nodes[id].l+1 == nodes[id].r){
        S+=nodes[id].sum;
        return ;
    }
    if(nodes[id].add)
       	down(id);
    int mid = (nodes[id].l+nodes[id].r)>>1;
    if(ql < mid){
       lqry(nodes[id].ls, ql, qr);
    }
    if(qr > mid){
       lqry(nodes[id].rs, ql, qr);
    }
    nodes[id].sum=0;
    if (nodes[id].ls != -1)
		nodes[id].sum += nodes[nodes[id].ls].sum;
	if (nodes[id].rs != -1)
		nodes[id].sum += nodes[nodes[id].rs].sum;
}

void update(int &id, int x,int y,int val)
{
    if(id == -1) return ;
    if(x==y) return;
    if(nodes[id].l+1 == nodes[id].r){
        nodes[id].sum+=val;
        return ;
    }
    if(x <= nodes[id].l  && nodes[id].r <= y){
    	 nodes[id].sum+=val;
    	 nodes[id].add+=val;
    	 return;
    }
    if(nodes[id].add)
    	down(id);
    int mid = (nodes[id].l+nodes[id].r)>>1;
    if(x<mid)
        update(nodes[id].ls, x, y,val);
    if(y>mid)
        update(nodes[id].rs, x, y,val);
    nodes[id].sum=0;
    if(nodes[id].ls!=-1)
    	nodes[id].sum+=nodes[nodes[id].ls].sum;
    if(nodes[id].rs!=-1)
        nodes[id].sum+=nodes[nodes[id].rs].sum;
}
void upd(int u, int v,int vv){
    while(id[u] != id[v]){
        if(id[u] > id[v]){
            swap(u, v);
        }
        int b = id[v];
        update(root[b], st[b], dep[v],vv);
        v = par[top[b]];
        if(mp.find(make_pair(top[b],par[top[b]]))!=mp.end())
        	val[mp[make_pair(top[b],par[top[b]])]]+=vv;
        else
        	val[mp[make_pair(par[top[b]],top[b])]]+=vv;
    }
    if(dep[u] > dep[v]){
        swap(u, v);
    }
    update(root[id[u]], dep[u], dep[v],vv);
}
void qry(int u, int v){
    while(id[u] != id[v]){
        if(id[u] > id[v]){
            swap(u, v);
        }
        int b = id[v];
        lqry(root[b], st[b], dep[v]);
        v = par[top[b]];
        if(mp.find(make_pair(top[b],par[top[b]]))!=mp.end()){
        	S+=val[mp[make_pair(top[b],par[top[b]])]];
        }
        else{
        	S+=val[mp[make_pair(par[top[b]],top[b])]];
        }
    }
    if(dep[u] > dep[v]){
        swap(u, v);
    }
    lqry(root[id[u]], dep[u], dep[v]);
}
struct ee{
	int x,y;
}edge[100010];
int main(){
    int m,x,y,u,v;
    scanf("%d",&n);
    init();
    for(int i=1;i<n;i++){
      scanf("%d%d",&x,&y);
      mp[make_pair(x,y)]=i;
      edge[i].x=x;edge[i].y=y;
      add_e(x,y);
      add_e(y,x);
    }
    initTree();

	scanf("%d", &m);
	for (int i = 0; i < m; i++) {
		scanf("%d%d",&u,&v);
		upd(u, v, 1);
	}
	for(int i=1;i<n;i++){
		S = 0;
		qry(edge[i].x,edge[i].y);
		if(i!=n-1)
			printf("%d ",S);
		else
			printf("%d\n",S);
	}
}