import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Queue;
import java.util.StringTokenizer;

public class C191 {
  static class FastScanner {
    BufferedReader br;
    StringTokenizer st;

    public FastScanner(InputStream in) {
      br = new BufferedReader(new InputStreamReader(in));
      st = new StringTokenizer("");
    }

    public int nextInt() throws IOException {
      if (st.hasMoreTokens()) return Integer.parseInt(st.nextToken());
      st = new StringTokenizer(br.readLine());
      return nextInt();
    }

    public String next() throws IOException {
      if(st.hasMoreTokens()) return st.nextToken();
      st = new StringTokenizer(br.readLine());
      return next();
    }
  }
  public static void main(String[] args) throws IOException {
    FastScanner in = new FastScanner(System.in);
    PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
    int n = in.nextInt();
    ArrayList<Integer>[] t = new ArrayList[n];
    for(int i = 0; i < n; i++) t[i] = new ArrayList<Integer>();
    int[] starts = new int[n-1];
    int[] ends = new int[n-1];
    for(int i = 0; i < n-1; i++) {
      int a = in.nextInt()-1;
      int b = in.nextInt()-1;
      t[a].add(b);
      t[b].add(a);
      starts[i]=a;
      ends[i]=b;
    }
    Queue<Integer> q = new ArrayDeque<Integer>();
    int[] depth = new int[n];
    Arrays.fill(depth, -1);
    depth[0]=0;
    q.add(0);
    while(!q.isEmpty()) {
      int at = q.poll();
      for(int adj : t[at])
        if(depth[adj]==-1) {
          depth[adj]=depth[at]+1;
          q.add(adj);
        }
    }
    LinkcutTree lct = new LinkcutTree(n);
    for(int i = 0; i < n; i++)
      for(int adj : t[i])
        if(depth[i]<depth[adj])
          lct.link(adj, i);

    int qu = in.nextInt();
    for(int i = 0; i < qu; i++) {
      int a = in.nextInt()-1;
      int b = in.nextInt()-1;
      lct.incToLCA(a, b, 1);
    }

    for(int i = 0; i < n-1; i++) {
      if(depth[starts[i]] < depth[ends[i]]) {
        out.printf("%d ", lct.valueAt(ends[i]));
      } else {
        out.printf("%d ", lct.valueAt(starts[i]));
      }
    }
    out.println();
    out.close();
  }
  static class LinkcutTree {
    int[] pp, p, l, r, carry, value;
    int NULL;
    public LinkcutTree(int n) {
      Arrays.fill(p = new int[n + 1], NULL = n);
      Arrays.fill(pp = new int[n + 1], NULL);
      Arrays.fill(l = new int[n + 1], NULL);
      Arrays.fill(r = new int[n + 1], NULL);
      carry = new int[n + 1];
      value = new int[n + 1];
    }
    int valueAt(int v) {
      access(v);
      return value[v];
    }
    void incToLCA(int v, int w, int x) {
      incPath(v,x); incPath(w,x);
      int lca = lca(v,w);
      incPath(lca,-2*x); // for this problem it is on edges so exclude the LCA...
      // to add LCA add "value[lca]+=x" here
    }
    void incPath(int v, int x) {
      access(v);
      value[v]+=x;
      carry[l[v]]+=x;
    }
    int lca(int v, int w) {
      access(v); access(w); splay(v);
      return pp[v]==NULL?v:pp[v];
    }
    int findRoot(int v) {
      access(v);
      for(; l[v]!=NULL; v=l[v]);
      splay(v);
      return v;
    }
    void cut(int v) {
      access(v);
      p[l[v]]=l[v]=NULL;
    }
    void link(int v, int w) {
      access(v); access(w);
      l[p[w]=v]=w;
    }
    void push(int v) {
      if(v!=NULL && carry[v]!=0) {
        value[v]+=carry[v];
        carry[l[v]]+=carry[v];
        carry[r[v]]+=carry[v];
        carry[v]=0;
      }
    }
    void access(int v) {
      splay(v);
      if(r[v]!=NULL) {p[r[v]]=NULL; pp[r[v]]=v;}
      r[v]=NULL;
      for(int w=pp[v]; pp[v]!=NULL; 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); // equivalent to splay here...
      }
    }
    void splay(int v) {
      for(; p[v]!=NULL; lift(v))
        if(l[l[p[p[v]]]]==v || r[r[p[p[v]]]]==v) lift(p[v]);
        else lift(v);
    }
    void lift(int v) {
      push(p[v]);
      push(v);
      if (p[v] == NULL) return;
      pp[v]=pp[p[v]];
      pp[p[v]]=NULL;
      int[] m=l, a=r;
      if(r[p[v]]==v) {m=r;a=l;}
      m[p[v]]=a[v];
      p[a[v]]=p[v];
      a[v]=p[v];
      p[v]=p[p[v]];
      p[a[v]]=v;
      if(p[v]!=NULL)
        if(l[p[v]]==a[v]) l[p[v]]=v;
        else r[p[v]]=v;
    }
  }
}
/*

5
3 4
4 5
1 4
2 4
3
2 3
1 3
3 5

*/


import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.StringTokenizer;
import java.util.concurrent.ArrayBlockingQueue;

public class C {
	BufferedReader in;
	StringTokenizer str;
	PrintWriter out;
	String SK;

	String next() throws IOException {
		while ((str == null) || (!str.hasMoreTokens())) {
			SK = in.readLine();
			if (SK == null)
				return null;
			str = new StringTokenizer(SK);
		}
		return str.nextToken();
	}

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

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

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

	class Edge {
		int v;
		int num;

		public Edge(int x, int nm) {
			v = x;
			num = nm;
		}
	}

	class Zapr {
		int number;
		int st, en;
		int res = -1;

		public Zapr(int a, int b) {
			st = a;
			en = b;
			number = a;
		}
	}

	int[] add;
	ArrayList<Edge>[] a;
	ArrayList<Zapr>[] b;

	int[] par;
	int[] dyn;

	int get(int v) {
		return par[v] = ((par[v] == v) ? v : get(par[v]));
	}

	void union(int l, int r, int num) {
		int v1 = get(r);
		int v2 = get(l);
		par[v2] = v1;
		dyn[v1] = num;
	}

	int[] was;

	void dfs3(int v, int par) {
		for (Zapr x : b[v]) {
			if (x.st != v) {
				int t;
				t = x.st;
				x.st = x.en;
				x.en = t;
			}
			if (was[x.en] == 1) {
				sum[x.st]++;
				sum[x.en]++;
				sum[dyn[get(x.en)]] -= 2;
			}
		}
		was[v] = 1;
		for (Edge i : a[v]) {
			if (was[i.v] == 0) {
				dfs3(i.v, v);
				union(v, i.v, v);
			}
		}
	}

	int[] sum;
	int[] res;

	void dfs(int v, int par, int parnum) {
		for (Edge i : a[v]) {
			if (i.v != par) {
				dfs(i.v, v, i.num);
				sum[v] += sum[i.v];
			}
		}
		if (parnum != -1) {
			res[parnum] = sum[v];
		}
	}

	void solve() throws IOException {
		int n = nextInt();
		par = new int[n];
		dyn = new int[n];
		add = new int[n];
		res = new int[n];
		was = new int[n];
		sum = new int[n];
		a = new ArrayList[n];
		b = new ArrayList[n];
		for (int i = 0; i < n; i++) {
			par[i] = i;
			dyn[i] = i;
			a[i] = new ArrayList<C.Edge>();
			b[i] = new ArrayList<C.Zapr>();
		}
		for (int i = 0; i < n - 1; i++) {
			int st = nextInt() - 1;
			int en = nextInt() - 1;
			a[st].add(new Edge(en, i));
			a[en].add(new Edge(st, i));
		}
		int k = nextInt();
		for (int i = 0; i < k; i++) {
			int st = nextInt() - 1;
			int en = nextInt() - 1;
			Zapr x = new Zapr(st, en);
			b[st].add(x);
			b[en].add(x);
		}
		dfs3(0, -1);
		dfs(0, -1, -1);
		for (int i = 0; i < n - 1; i++) {
			out.print(res[i] + " ");
		}

	}

	void run() throws IOException {
		in = new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(System.out);
		solve();
		out.close();
	}

	public static void main(String[] args) throws IOException {
		new C().run();
	}

}


import java.io.*;
import java.util.*;
import java.math.*;
import java.awt.geom.*;

import static java.lang.Math.*;

public class Main implements Runnable {

	static String filename = "";

	class Edge {
		int to, number;

		public Edge(int to, int number) {
			this.to = to;
			this.number = number;
		}

		@Override
		public String toString() {
			return Integer.toString(to);
		}
	}

	int n;
	ArrayList<Edge>[] graph;
	ArrayList<Integer>[] query;
	ArrayList<Edge>[] children;
	int[] dp;
	boolean[] visited;
	int[] parent;
	int[] rank;
	int[] ancestor;
	int[] answer;

	void hang(int from) {
		visited[from] = true;
		for (Edge e : graph[from]) {
			if (!visited[e.to]) {
				children[from].add(e);
				hang(e.to);
			}
		}
	}

	int findSet(int n) {
		if (parent[n] == n) {
			return n;
		} else {
			return parent[n] = findSet(parent[n]);
		}
	}

	void union(int n1, int n2, int anc) {
		int s1 = findSet(n1), s2 = findSet(n2);
		if (rank[s1] < rank[s2]) {
			int temp = s1;
			s1 = s2;
			s2 = temp;
		}
		parent[s2] = s1;
		rank[s1] = max(rank[s1], rank[s2] + 1);
		ancestor[s1] = anc;
	}

	void tarjan(int from) {
		visited[from] = true;
		for (int q : query[from]) {
			if (visited[q]) {
				dp[from]++;
				dp[q]++;
				dp[ancestor[findSet(q)]] -= 2;
				//out.println((from + 1) + " " + (q + 1) + " " + (ancestor[findSet(q)] + 1));
			}
		}
		for (Edge e : children[from]) {
			tarjan(e.to);
			union(from, e.to, from);
		}
	}

	void getAnswer(int from) {
		visited[from] = true;
		for (Edge e : children[from]) {
			getAnswer(e.to);
			answer[e.number] = dp[e.to];
			dp[from] += dp[e.to];
		}
	}

	public void solve() throws Exception {
		n = sc.nextInt();
		graph = new ArrayList[n];
		query = new ArrayList[n];
		children = new ArrayList[n];
		dp = new int[n];
		visited = new boolean[n];
		parent = new int[n];
		rank = new int[n];
		ancestor = new int[n];
		answer = new int[n - 1];
		for (int i = 0; i < n; i++) {
			graph[i] = new ArrayList<Edge>();
			query[i] = new ArrayList<Integer>();
			children[i] = new ArrayList<Edge>();
			parent[i] = i;
			ancestor[i] = i;
		}
		for (int i = 0; i < n - 1; i++) {
			int from = sc.nextInt() - 1, to = sc.nextInt() - 1;
			graph[from].add(new Edge(to, i));
			graph[to].add(new Edge(from, i));
		}
		int k = sc.nextInt();
		for (int i = 0; i < k; i++) {
			int from = sc.nextInt() - 1, to = sc.nextInt() - 1;
			query[from].add(to);
			query[to].add(from);
		}
		hang(0);
		Arrays.fill(visited, false);
		tarjan(0);
		Arrays.fill(visited, false);
		getAnswer(0);
		for (int i : answer) {
			out.print(i + " ");
		}
		out.println();
	}

	BufferedReader in;
	PrintWriter out;
	FastScanner sc;

	public static void main(String[] args) {
		new Thread(null, new Main(), "", 1 << 25).start();
	}

	@Override
	public void run() {
		try {
			init();
			solve();
		} catch (Throwable e) {
			throw new RuntimeException(e);
		} finally {
			out.close();
		}
	}

	void init() throws Exception {
		in = new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(System.out);
		sc = new FastScanner(in);
	}
}

class FastScanner {

	BufferedReader reader;
	StringTokenizer strTok;

	public FastScanner(BufferedReader reader) {
		this.reader = reader;
	}

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

		return strTok.nextToken();
	}

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

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

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

	public BigInteger nextBigInteger() throws IOException {
		return new BigInteger(nextToken());
	}

}


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

public class C {

	final String filename = new String("C").toLowerCase();

	ArrayList<Edge>[] graph;

	class Edge {
		int from, to, id;

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

	List<Integer>[] queries;
	int[] ans;
	boolean[] used;

	Set<Integer> dfs(int u) {
		used[u] = true;
		Set<Integer> currentQs = new HashSet<Integer>(queries[u]);
		for (Edge e : graph[u]) {
			if (!used[e.to]) {
				Set<Integer> newQs = dfs(e.to);
				ans[e.id] = newQs.size();
				if (newQs.size() > currentQs.size()) {
					Set<Integer> tmp = newQs;
					newQs = currentQs;
					currentQs = tmp;
				}
				for (int i : newQs) {
					if (currentQs.contains(i)) {
						currentQs.remove(i);
					} else {
						currentQs.add(i);
					}
				}
			}
		}
		return currentQs;
	}

	void solve() throws Exception {
		int n = nextInt();
		graph = new ArrayList[n];
		queries = new List[n];
		for (int i = 0; i < n; i++) {
			graph[i] = new ArrayList<Edge>();
			queries[i] = new ArrayList<Integer>();
		}
		used = new boolean[n];
		for (int i = 0; i < n - 1; i++) {
			int x = nextInt() - 1;
			int y = nextInt() - 1;
			graph[x].add(new Edge(x, y, i));
			graph[y].add(new Edge(y, x, i));
		}
		int k = nextInt();
		for (int i = 0; i < k; i++) {
			int x = nextInt() - 1;
			int y = nextInt() - 1;
			if (x == y) {
				continue;
			}
			queries[x].add(i);
			queries[y].add(i);
		}
		ans = new int[n - 1];

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

	void run() {
		try {
//			in = new BufferedReader(new FileReader(filename + ".in"));
//			out = new PrintWriter(filename + ".out");
			 in = new BufferedReader(new InputStreamReader(System.in));
			 out = new PrintWriter(System.out);

			solve();

			out.close();
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}
	}

	BufferedReader in;
	StringTokenizer st;
	PrintWriter out;

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

	int nextInt() throws Exception {
		return Integer.parseInt(nextToken());
	}

	long nextLong() throws Exception {
		return Long.parseLong(nextToken());
	}

	double nextDouble() throws Exception {
		return Double.parseDouble(nextToken());
	}

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

}


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

public class C {

	final String filename = new String("C").toLowerCase();

	ArrayList<Edge>[] graph;

	class Edge {
		int from, to, id;

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

	List<Integer>[] queries;
	int[] ans;
	boolean[] used;

	Set<Integer> dfs(int u) {
		used[u] = true;
		Set<Integer> currentQs = new HashSet<Integer>(queries[u]);
		for (Edge e : graph[u]) {
			if (!used[e.to]) {
				Set<Integer> newQs = dfs(e.to);
				ans[e.id] = newQs.size();
				if (newQs.size() > currentQs.size()) {
					Set<Integer> tmp = newQs;
					newQs = currentQs;
					currentQs = tmp;
				}
				for (int i : newQs) {
					if (currentQs.contains(i)) {
						currentQs.remove(i);
					} else {
						currentQs.add(i);
					}
				}
			}
		}
		return currentQs;
	}

	void solve() throws Exception {
		int n = nextInt();
		graph = new ArrayList[n];
		queries = new List[n];
		for (int i = 0; i < n; i++) {
			graph[i] = new ArrayList<Edge>();
			queries[i] = new ArrayList<Integer>();
		}
		used = new boolean[n];
		for (int i = 0; i < n - 1; i++) {
			int x = nextInt() - 1;
			int y = nextInt() - 1;
			graph[x].add(new Edge(x, y, i));
			graph[y].add(new Edge(y, x, i));
		}
		int k = nextInt();
		for (int i = 0; i < k; i++) {
			int x = nextInt() - 1;
			int y = nextInt() - 1;
			queries[x].add(i);
			queries[y].add(i);
		}
		ans = new int[n - 1];

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

	void run() {
		try {
//			in = new BufferedReader(new FileReader(filename + ".in"));
//			out = new PrintWriter(filename + ".out");
			 in = new BufferedReader(new InputStreamReader(System.in));
			 out = new PrintWriter(System.out);

			solve();

			out.close();
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}
	}

	BufferedReader in;
	StringTokenizer st;
	PrintWriter out;

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

	int nextInt() throws Exception {
		return Integer.parseInt(nextToken());
	}

	long nextLong() throws Exception {
		return Long.parseLong(nextToken());
	}

	double nextDouble() throws Exception {
		return Double.parseDouble(nextToken());
	}

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

}


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 ProblemC {

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


//package round121;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;

public class C {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
		int n = ni();
		int[] from = new int[n-1];
		int[] to = new int[n-1];
		int[] w = new int[n-1];
		for(int i = 0;i < n-1;i++){
			from[i] = ni()-1;
			to[i] = ni()-1;
			w[i] = i;
		}
		int[][][] g = packWU(n, from, to, w);
		int[][] pars = parent(g, 0);
		int[] par = pars[0];
		int[] ord = pars[1];
		int[] dep = pars[2];
		int[] iord = new int[n];
		for(int i = 0;i < n;i++)iord[ord[i]] = i;
		int[][] sp = sparseParents(par, iord);

		int K = ni();
		int[] sc = new int[n];
		for(int i = 0;i < K;i++){
			int f = ni()-1, t = ni() - 1;
			int lca = lca(f, t, sp, dep);

			sc[f]++;
			sc[t]++;
			sc[lca] -= 2;
		}

		int[] ret = new int[n-1];
		for(int i = n-1;i >= 0;i--){
			int cur = ord[i];
			int pl = -1;
			for(int[] e : g[cur]){
				if(par[cur] != e[0]){
					sc[cur] += sc[e[0]];
				}else{
					pl = e[1];
				}
			}
			if(pl != -1)ret[pl] = sc[cur];
		}
		for(int i = 0;i < n-1;i++){
			if(i > 0)out.print(" ");
			out.print(ret[i]);
		}
		out.println();
	}

	public static int lca(int a, int b, int[][] spar, int[] depth)
	{
		if(depth[a] < depth[b]){
			b = ancestor(b, depth[b]-depth[a], spar);
		}else if(depth[a] > depth[b]){
			a = ancestor(a, depth[a]-depth[b], spar);
		}

		int low = -1;
		int high = depth[a];
		while(high - low > 1){
			int x = (low + high) / 2;
			if(ancestor(a, x, spar) == ancestor(b, x, spar)){
				high = x;
			}else{
				low = x;
			}
		}
		return ancestor(a, high, spar);
	}

	protected static int ancestor(int a, int m, int[][] spar)
	{
		for(int i = 0;m > 0 && a != -1;m>>>=1,i++){
			if(m%2==1)a = spar[i][a];
		}
		return a;
	}

	public static int[][] sparseParents(int[] par, int[] iord)
	{
		int n = par.length;
		int m = Integer.numberOfTrailingZeros(Integer.highestOneBit(n-1))+1;
		int[][] pars = new int[m][n];
		pars[0] = par;
		for(int j = 1;j < m;j++){
			for(int i = n-1;i >= 0;i--){
				pars[j][iord[i]] = pars[j-1][iord[i]] == -1 ? -1 : pars[j-1][pars[j-1][iord[i]]];
			}
		}
		return pars;
	}

	public static int[][] parent(int[][][] g, int root)
	{
		int n = g.length;
		int[] par = new int[n];
		Arrays.fill(par, -1);

		int[] q = new int[n];
		q[0] = root;
		int[] dep = new int[n];
		dep[root] = 0;
		for(int p = 0, r = 1;p < r;p++) {
			int cur = q[p];
			for(int[] nex : g[cur]){
				if(par[cur] != nex[0]){
					q[r++] = nex[0];
					dep[nex[0]] = dep[cur] + 1;
					par[nex[0]] = cur;
				}
			}
		}
		return new int[][]{par, q, dep};
	}

	public static int[][][] packWU(int n, int[] from, int[] to, int[] w)
	{
		int[][][] g = new int[n][][];
		int[] p = new int[n];
		for(int f : from)p[f]++;
		for(int t : to)p[t]++;
		for(int i = 0;i < n;i++)g[i] = new int[p[i]][2];
		for(int i = 0;i < from.length;i++){
			--p[from[i]];
			g[from[i]][p[from[i]]][0] = to[i];
			g[from[i]][p[from[i]]][1] = w[i];
			--p[to[i]];
			g[to[i]][p[to[i]]][0] = from[i];
			g[to[i]][p[to[i]]][1] = w[i];
		}
		return g;
	}

	void run() throws Exception
	{
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception
	{
		new C().run();
	}

	public int ni()
	{
		try {
			int num = 0;
			boolean minus = false;
			while((num = is.read()) != -1 && !((num >= '0' && num <= '9') || num == '-'));
			if(num == '-'){
				num = 0;
				minus = true;
			}else{
				num -= '0';
			}

			while(true){
				int b = is.read();
				if(b >= '0' && b <= '9'){
					num = num * 10 + (b - '0');
				}else{
					return minus ? -num : num;
				}
			}
		} catch (IOException e) {
		}
		return -1;
	}

	public long nl()
	{
		try {
			long num = 0;
			boolean minus = false;
			while((num = is.read()) != -1 && !((num >= '0' && num <= '9') || num == '-'));
			if(num == '-'){
				num = 0;
				minus = true;
			}else{
				num -= '0';
			}

			while(true){
				int b = is.read();
				if(b >= '0' && b <= '9'){
					num = num * 10 + (b - '0');
				}else{
					return minus ? -num : num;
				}
			}
		} catch (IOException e) {
		}
		return -1;
	}

	public String ns()
	{
		try{
			int b = 0;
			StringBuilder sb = new StringBuilder();
			while((b = is.read()) != -1 && (b == '\r' || b == '\n' || b == ' '));
			if(b == -1)return "";
			sb.append((char)b);
			while(true){
				b = is.read();
				if(b == -1)return sb.toString();
				if(b == '\r' || b == '\n' || b == ' ')return sb.toString();
				sb.append((char)b);
			}
		} catch (IOException e) {
		}
		return "";
	}

	public char[] ns(int n)
	{
		char[] buf = new char[n];
		try{
			int b = 0, p = 0;
			while((b = is.read()) != -1 && (b == ' ' || b == '\r' || b == '\n'));
			if(b == -1)return null;
			buf[p++] = (char)b;
			while(p < n){
				b = is.read();
				if(b == -1 || b == ' ' || b == '\r' || b == '\n')break;
				buf[p++] = (char)b;
			}
			return Arrays.copyOf(buf, p);
		} catch (IOException e) {
		}
		return null;
	}

	double nd() { return Double.parseDouble(ns()); }
	boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


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

public class C {

	private class Edge {
		public int v;
		public int id;

		public Edge(int v, int id) {
			this.v = v;
			this.id = id;
		}
	}

	private void solve() throws IOException {
		int n = nextInt();

		ArrayList<Edge>[] g = new ArrayList[n];
		for (int i = 0; i < n; i++) {
			g[i] = new ArrayList<Edge>();
		}
		int[] res = new int[n];

		for (int i = 1; i < n; i++) {
			int u = nextInt() - 1;
			int v = nextInt() - 1;
			g[u].add(new Edge(v, i));
			g[v].add(new Edge(u, i));
		}

		HashSet<Integer>[] p = new HashSet[n];
		for (int i = 0; i < n; i++) {
			p[i] = new HashSet<Integer>();
		}
		int k = nextInt();
		for (int i = 0; i < k; i++) {
			int u = nextInt() - 1;
			int v = nextInt() - 1;

			if (u != v) {
				p[u].add(i);
				p[v].add(i);
			}
		}

		dfs(0, -1, g, p, res);
		for (int i = 1; i < n; i++) {
			print(res[i] + " ");
		}
	}

	private HashSet<Integer> union(HashSet<Integer> s1, HashSet<Integer> s2) {
		if (s2.size() > s1.size()) {
			return union(s2, s1);
		}

		for (Integer x: s2) {
			if (s1.contains(x)) {
				s1.remove(x);
			} else {
				s1.add(x);
			}
		}

		return s1;
	}

	private HashSet<Integer> dfs(int u, int prev, ArrayList<Edge>[] g,
			HashSet<Integer>[] p, int[] ans) {

		HashSet<Integer> res = p[u];
		for (Edge e: g[u]) {
			if (e.v != prev) {
				HashSet<Integer> set = dfs(e.v, u, g, p, ans);
				ans[e.id] += set.size();
				res = union(res, set);
			}
		}

		return res;
	}
	private String nextToken() throws IOException {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			tokenizer = new StringTokenizer(reader.readLine());
		}
		return tokenizer.nextToken();
	}

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

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

	private long nextLong() throws IOException {
		return Long.parseLong(nextToken());
	}

	private void print(Object o) {
		writer.print(o);
	}

	private void println(Object o) {
		writer.println(o);
	}

	private void printf(String format, Object... o) {
		writer.printf(format, o);
	}

	public static void main(String[] args) {
		long time = System.currentTimeMillis();
		Locale.setDefault(Locale.US);
		new C().run();
		System.err.printf("%.3f\n", 1e-3 * (System.currentTimeMillis() - time));
	}

	BufferedReader reader;
	StringTokenizer tokenizer;
	PrintWriter writer;

	private void run() {
		try {
			reader = new BufferedReader(new InputStreamReader(System.in));
			writer = new PrintWriter(System.out);
			solve();
			reader.close();
			writer.close();
		} catch (IOException e) {
			e.printStackTrace();
			System.exit(13);
		}
	}
}


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

public class C {

	private class Edge {
		public int v;
		public int id;

		public Edge(int v, int id) {
			this.v = v;
			this.id = id;
		}
	}

	private void solve() throws IOException {
		int n = nextInt();

		ArrayList<Edge>[] g = new ArrayList[n];
		for (int i = 0; i < n; i++) {
			g[i] = new ArrayList<Edge>();
		}
		int[] res = new int[n];

		for (int i = 1; i < n; i++) {
			int u = nextInt() - 1;
			int v = nextInt() - 1;
			g[u].add(new Edge(v, i));
			g[v].add(new Edge(u, i));
		}

		HashSet<Integer>[] p = new HashSet[n];
		for (int i = 0; i < n; i++) {
			p[i] = new HashSet<Integer>();
		}
		int k = nextInt();
		for (int i = 0; i < k; i++) {
			int u = nextInt() - 1;
			int v = nextInt() - 1;
			p[u].add(i);
			p[v].add(i);
		}

		dfs(0, -1, g, p, res);
		for (int i = 1; i < n; i++) {
			print(res[i] + " ");
		}
	}

	private HashSet<Integer> union(HashSet<Integer> s1, HashSet<Integer> s2) {
		if (s2.size() > s1.size()) {
			return union(s2, s1);
		}

		for (Integer x: s2) {
			if (s1.contains(x)) {
				s1.remove(x);
			} else {
				s1.add(x);
			}
		}

		return s1;
	}

	private HashSet<Integer> dfs(int u, int prev, ArrayList<Edge>[] g,
			HashSet<Integer>[] p, int[] ans) {

		HashSet<Integer> res = p[u];
		for (Edge e: g[u]) {
			if (e.v != prev) {
				HashSet<Integer> set = dfs(e.v, u, g, p, ans);
				ans[e.id] += set.size();
				res = union(res, set);
			}
		}

		return res;
	}
	private String nextToken() throws IOException {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			tokenizer = new StringTokenizer(reader.readLine());
		}
		return tokenizer.nextToken();
	}

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

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

	private long nextLong() throws IOException {
		return Long.parseLong(nextToken());
	}

	private void print(Object o) {
		writer.print(o);
	}

	private void println(Object o) {
		writer.println(o);
	}

	private void printf(String format, Object... o) {
		writer.printf(format, o);
	}

	public static void main(String[] args) {
		long time = System.currentTimeMillis();
		Locale.setDefault(Locale.US);
		new C().run();
		System.err.printf("%.3f\n", 1e-3 * (System.currentTimeMillis() - time));
	}

	BufferedReader reader;
	StringTokenizer tokenizer;
	PrintWriter writer;

	private void run() {
		try {
			reader = new BufferedReader(new InputStreamReader(System.in));
			writer = new PrintWriter(System.out);
			solve();
			reader.close();
			writer.close();
		} catch (IOException e) {
			e.printStackTrace();
			System.exit(13);
		}
	}
}


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

public class taskC {

	PrintWriter out;
	BufferedReader br;
	StringTokenizer st;

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

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

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

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

	int get(int i, int[] pr) {
		while (pr[i] != i) {
			pr[i] = get(pr[i], pr);
			break;
		}
		return pr[i];
	}

	Random rnd;

	void union(int a, int b, int[] pr) {
		if ((a == -1) || (b == -1))
			return;
		a = get(a, pr);
		b = get(b, pr);
		if (a == b)
			return;
		pr[a] = b;
	}

	void dfs(int t, int p, ArrayList<Integer>[] e, ArrayList<Integer>[] q, int[] st, boolean[] was, int[] pr) {
		if (was[t])
			return;
		for (int i = 0; i < q[t].size(); i++) {
			if (was[q[t].get(i)]) {
				st[q[t].get(i)]++;
				st[t]++;
				st[get(q[t].get(i), pr)]-=2;
			}
		}
		was[t] = true;
		for (int i = 0; i < e[t].size(); i++) {
			dfs(e[t].get(i), t, e, q, st, was, pr);
		}
		union(t, p, pr);
	}

	int dfs2(int t, ArrayList<Integer>[] e, ArrayList<Integer>[] num, int[] st, boolean[] was, int[] ans) {
		was[t] = true;
		int sum = 0;
		for (int i = 0; i < e[t].size(); i++) {
			if (was[e[t].get(i)])
				continue;
			int x = dfs2(e[t].get(i), e, num, st, was, ans);
			ans[num[t].get(i)] = x;
			sum += x;
		}
		return sum + st[t];
	}

	public void solve() throws IOException {
		Random rnd = new Random();
		int n = nextInt();

		ArrayList<Integer>[] e = new ArrayList[n];
		ArrayList<Integer>[] num = new ArrayList[n];

		for (int i = 0; i < n; i++) {
			e[i] = new ArrayList<Integer>();
			num[i] = new ArrayList<Integer>();
		}
		for (int i = 0; i < n - 1; i++) {
			int a = nextInt() - 1;
			int b = nextInt() - 1;
			e[a].add(b);
			e[b].add(a);
			num[a].add(i);
			num[b].add(i);
		}
		int[] p = new int[n];
		int[] pr = new int[n];
		for (int i = 0; i < n; i++) {
			pr[i] = i;
		}
		ArrayList<Integer>[] q = new ArrayList[n];
		ArrayList<Integer>[] numq = new ArrayList[n];
		int k = nextInt();
		for (int i = 0; i < n; i++) {
			q[i] = new ArrayList<Integer>();
			numq[i] = new ArrayList<Integer>();
		}
		for (int i = 0; i < k; i++) {
			int a = nextInt() - 1;
			int b = nextInt() - 1;
			q[a].add(b);
			q[b].add(a);
			numq[a].add(i);
			numq[b].add(i);
		}
		int[] st = new int[n];
		boolean[] was = new boolean[n];
		dfs(0, -1, e, q, st, was, pr);
		was = new boolean[n];
		int[] ans = new int[n - 1];
		dfs2(0, e, num, st, was, ans);
		for (int i = 0; i < n - 1; i++) {
			out.print(ans[i] + " ");
		}
	}

	public void run() {
		try {
			br = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(System.out);

			//br = new BufferedReader(new FileReader("taskC.in"));
			//out = new PrintWriter("taskC.out");

			solve();

			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

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


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;
import java.util.Map.Entry;

public class e121_FASTER {

    public static void debug(Object... obs)
    {
        System.out.println(Arrays.deepToString(obs));
    }

    static Node[]ns;
    static Edge[]e;

    public static void main(String[] args) throws Exception
    {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st=new StringTokenizer(br.readLine());

        int n=Integer.parseInt(st.nextToken());
        ns=new Node[n];
        e=new Edge[n-1];
        for(int i=0;i<n;i++)
            ns[i]=new Node(i);
        for(int i=0;i<n-1;i++)
        {
            st=new StringTokenizer(br.readLine());
            int a=Integer.parseInt(st.nextToken())-1;
            int b=Integer.parseInt(st.nextToken())-1;

            e[i]=new Edge(a,b);
            ns[a].al.put(b,e[i]);
            ns[b].al.put(a,e[i]);
        }

        int k=Integer.parseInt(br.readLine());
        for(int i=0;i<k;i++)
        {
            st=new StringTokenizer(br.readLine());
            int a=Integer.parseInt(st.nextToken())-1;
            int b=Integer.parseInt(st.nextToken())-1;

            if(a==b) continue;

            ns[a].seen.add(i);
            ns[b].seen.add(i);
        }

        go(0, 0);

        for(Edge e1 : e)
        {
            System.out.print(e1.cnt+" ");
        }
        System.out.println();
    }

    private static Set<Integer> go(int i, int from)
    {
        Node n=ns[i];

        Set<Integer> seen = n.seen;

        for(Entry<Integer, Edge> ze : n.al.entrySet())
        {
            int k = ze.getKey();
            if(k == from) continue;

            Set<Integer> fm = go(k,i);
            //debug(i+1,k+1,fm.size());
            ze.getValue().cnt+=fm.size();

            seen = merge(fm,seen);
        }

        return seen;
    }

    private static Set<Integer> merge(Set<Integer> n1, Set<Integer> n2)
    {
        Set<Integer> l=n2,r=n1;
        if(n1.size() > n2.size())
        {
            l = n1;
            r = n2;
        }
        Set<Integer> res = l;
        for(int i : r)
        {
            if(res.contains(i))
            {
                res.remove(i);
            }
            else
            {
                res.add(i);
            }
        }
        return res;
    }

    private static class Edge
    {
        int f;
        int t;
        int cnt;
        public Edge(int f, int t)
        {
            super();
            this.f = f;
            this.t = t;
        }
    }

    private static class Node implements Comparable<Node>
    {

        int id;
        Set<Integer>seen = new HashSet<Integer>();
        Map<Integer,Edge> al = new HashMap<Integer,Edge>();

        public Node(int id)
        {
            super();
            this.id = id;
        }

        public int left()
        {
            int z = al.keySet().iterator().next();
            return z;
        }

        public int compareTo(Node arg0)
        {
            if(al.size() == arg0.al.size())
            {
                return id - arg0.id;
            }
            return al.size() - arg0.al.size();
        }

        @Override
        public boolean equals(Object obj)
        {
            if(obj == this) return true;
            if( !(obj instanceof Node)) return false;
            Node n = (Node)obj;
            return n.id == id;
        }
    }

}


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;

public class e121 {

    public static void debug(Object... obs)
    {
        System.out.println(Arrays.deepToString(obs));
    }

    public static void main(String[] args) throws Exception
    {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st=new StringTokenizer(br.readLine());

        int n=Integer.parseInt(st.nextToken());
        Node[]ns=new Node[n];
        Edge[]e=new Edge[n-1];
        for(int i=0;i<n;i++)
            ns[i]=new Node(i);
        for(int i=0;i<n-1;i++)
        {
            st=new StringTokenizer(br.readLine());
            int a=Integer.parseInt(st.nextToken())-1;
            int b=Integer.parseInt(st.nextToken())-1;

            e[i]=new Edge(a,b);
            ns[a].al.put(b,e[i]);
            ns[b].al.put(a,e[i]);
        }

        int k=Integer.parseInt(br.readLine());
        for(int i=0;i<k;i++)
        {
            st=new StringTokenizer(br.readLine());
            int a=Integer.parseInt(st.nextToken())-1;
            int b=Integer.parseInt(st.nextToken())-1;

            ns[a].seen.add(i);
            ns[b].seen.add(i);
        }
        TreeSet<Node>pq=new TreeSet<Node>();
        pq.addAll(Arrays.asList(ns));

        while(!pq.isEmpty())
        {
            Node n1 = pq.pollFirst();
            if(n1.al.size()==0) continue;

            Node n2 = ns[n1.left()];
            //object id remove
            pq.remove(n2);
            n2.al.remove(n1.id);
            pq.add(n2);

            int c = n1.seen.size();
            n1.al.get(n1.left()).cnt+=c;
            merge(n1,n2);
        }

        for(Edge e1 : e)
        {
            System.out.print(e1.cnt+" ");
        }
        System.out.println();
    }

    private static void merge(Node n1, Node n2)
    {
        Node l=n2,r=n1;
        if(n1.seen.size() > n2.seen.size())
        {
            l = n1;
            r = n2;
        }
        Set<Integer> res = l.seen;
        for(int i : r.seen)
        {
            if(res.contains(i))
            {
                res.remove(i);
            }
            else
            {
                res.add(i);
            }
        }
        n2.seen = res;
    }

    private static class Edge
    {
        int f;
        int t;
        int cnt;
        public Edge(int f, int t)
        {
            super();
            this.f = f;
            this.t = t;
        }
    }

    private static class Node implements Comparable<Node>
    {

        int id;
        Set<Integer>seen = new HashSet<Integer>();
        Map<Integer,Edge> al = new HashMap<Integer,Edge>();

        public Node(int id)
        {
            super();
            this.id = id;
        }

        public int left()
        {
            int z = al.keySet().iterator().next();
            return z;
        }

        public int compareTo(Node arg0)
        {
            if(al.size() == arg0.al.size())
            {
                return id - arg0.id;
            }
            return al.size() - arg0.al.size();
        }
    }
}


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;

public class e121 {

    public static void debug(Object... obs)
    {
        System.out.println(Arrays.deepToString(obs));
    }

    public static void main(String[] args) throws Exception
    {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st=new StringTokenizer(br.readLine());

        int n=Integer.parseInt(st.nextToken());
        Node[]ns=new Node[n];
        Edge[]e=new Edge[n-1];
        for(int i=0;i<n;i++)
            ns[i]=new Node(i);
        for(int i=0;i<n-1;i++)
        {
            st=new StringTokenizer(br.readLine());
            int a=Integer.parseInt(st.nextToken())-1;
            int b=Integer.parseInt(st.nextToken())-1;

            e[i]=new Edge(a,b);
            ns[a].al.put(b,e[i]);
            ns[b].al.put(a,e[i]);
        }

        int k=Integer.parseInt(br.readLine());
        for(int i=0;i<k;i++)
        {
            st=new StringTokenizer(br.readLine());
            int a=Integer.parseInt(st.nextToken())-1;
            int b=Integer.parseInt(st.nextToken())-1;

            ns[a].seen.add(i);
            ns[b].seen.add(i);
        }
        TreeSet<Node>pq=new TreeSet<Node>();
        pq.addAll(Arrays.asList(ns));

        while(!pq.isEmpty())
        {
            Node n1 = pq.pollFirst();
            if(n1.al.size()==0) continue;

            Node n2 = ns[n1.left()];
            //object id remove
            pq.remove(n2);
            n2.al.remove(n1.id);
            pq.add(n2);

            int c = n1.seen.size();
            n1.al.get(n1.left()).cnt+=c;
            merge(n1,n2);
        }

        for(Edge e1 : e)
        {
            System.out.print(e1.cnt+" ");
        }
        System.out.println();
    }

    private static void merge(Node n1, Node n2)
    {
        Node l=n2,r=n1;
        if(n1.seen.size() > n2.seen.size())
        {
            l = n1;
            r = n2;
        }
        Set<Integer> res = l.seen;
        for(int i : r.seen)
        {
            if(res.contains(i))
            {
                res.remove(i);
            }
            else
            {
                res.add(i);
            }
        }
        n2.seen = res;
    }

    private static class Edge
    {
        int f;
        int t;
        int cnt;
        public Edge(int f, int t)
        {
            super();
            this.f = f;
            this.t = t;
        }
    }

    private static class Node implements Comparable<Node>
    {

        int id;
        Set<Integer>seen = new HashSet<Integer>();
        Map<Integer,Edge> al = new HashMap<Integer,Edge>();

        public Node(int id)
        {
            super();
            this.id = id;
        }

        public int left()
        {
            int z = al.keySet().iterator().next();
            return z;
        }

        public int compareTo(Node arg0)
        {
            if(al.size() == arg0.al.size())
            {
                return id - arg0.id;
            }
            return al.size() - arg0.al.size();
        }

        @Override
        public boolean equals(Object obj)
        {
            if(obj == this) return true;
            if( !(obj instanceof Node)) return false;
            Node n = (Node)obj;
            return n.id == id;
        }
    }

}


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;

public class e121 {

    public static void debug(Object... obs)
    {
        System.out.println(Arrays.deepToString(obs));
    }

    public static void main(String[] args) throws Exception
    {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st=new StringTokenizer(br.readLine());

        int n=Integer.parseInt(st.nextToken());
        Node[]ns=new Node[n];
        Edge[]e=new Edge[n-1];
        for(int i=0;i<n;i++)
            ns[i]=new Node(i);
        for(int i=0;i<n-1;i++)
        {
            st=new StringTokenizer(br.readLine());
            int a=Integer.parseInt(st.nextToken())-1;
            int b=Integer.parseInt(st.nextToken())-1;

            e[i]=new Edge(a,b);
            ns[a].al.put(b,e[i]);
            ns[b].al.put(a,e[i]);
        }

        int k=Integer.parseInt(br.readLine());
        for(int i=0;i<k;i++)
        {
            st=new StringTokenizer(br.readLine());
            int a=Integer.parseInt(st.nextToken())-1;
            int b=Integer.parseInt(st.nextToken())-1;

            ns[a].seen.add(i);
            ns[b].seen.add(i);
        }
        TreeSet<Node>pq=new TreeSet<Node>();
        pq.addAll(Arrays.asList(ns));

        while(!pq.isEmpty())
        {
            Node n1 = pq.pollFirst();
            if(n1.al.size()==0) continue;

            Node n2 = ns[n1.left()];
            //object id remove
            pq.remove(n2);
            n2.al.remove(n1.id);
            pq.add(n2);

            int c = n1.seen.size();
            n1.al.get(n1.left()).cnt+=c;
            merge(n1,n2);
        }

        for(Edge e1 : e)
        {
            System.out.print(e1.cnt+" ");
        }
        System.out.println();
    }

    private static void merge(Node n1, Node n2)
    {
        Node l=n2,r=n1;
        if(n1.seen.size() > n2.seen.size())
        {
            l = n1;
            r = n2;
        }
        Set<Integer> res = l.seen;
        for(Integer i : r.seen)
        {
            if(res.contains(i))
            {
                res.remove(i);
            }
            else
            {
                res.add(i);
            }
        }
        n2.seen = res;
    }

    private static class Edge
    {
        int f;
        int t;
        int cnt;
        public Edge(int f, int t)
        {
            super();
            this.f = f;
            this.t = t;
        }
    }

    private static class Node implements Comparable<Node>
    {

        int id;
        Set<Integer>seen = new HashSet<Integer>();
        Map<Integer,Edge> al = new HashMap<Integer,Edge>();

        public Node(int id)
        {
            super();
            this.id = id;
        }

        public int left()
        {
            int z = al.keySet().iterator().next();
            return z;
        }

        public int compareTo(Node arg0)
        {
            if(al.size() == arg0.al.size())
            {
                return id - arg0.id;
            }
            return al.size() - arg0.al.size();
        }
    }
}


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;

public class e121 {

    public static void debug(Object... obs)
    {
        System.out.println(Arrays.deepToString(obs));
    }

    public static void main(String[] args) throws Exception
    {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st=new StringTokenizer(br.readLine());

        int n=Integer.parseInt(st.nextToken());
        Node[]ns=new Node[n];
        Edge[]e=new Edge[n-1];
        for(int i=0;i<n;i++)
            ns[i]=new Node(i);
        for(int i=0;i<n-1;i++)
        {
            st=new StringTokenizer(br.readLine());
            int a=Integer.parseInt(st.nextToken())-1;
            int b=Integer.parseInt(st.nextToken())-1;

            e[i]=new Edge(a,b);
            ns[a].al.put(b,e[i]);
            ns[b].al.put(a,e[i]);
        }

        int k=Integer.parseInt(br.readLine());
        for(int i=0;i<k;i++)
        {
            st=new StringTokenizer(br.readLine());
            int a=Integer.parseInt(st.nextToken())-1;
            int b=Integer.parseInt(st.nextToken())-1;

            if(a==b) continue;

            ns[a].seen.add(i);
            ns[b].seen.add(i);
        }
        TreeSet<Node>pq=new TreeSet<Node>();
        pq.addAll(Arrays.asList(ns));

        while(!pq.isEmpty())
        {
            Node n1 = pq.pollFirst();
            if(n1.al.size()==0) continue;

            Node n2 = ns[n1.left()];
            //object id remove
            pq.remove(n2);
            n2.al.remove(n1.id);
            pq.add(n2);

            int c = n1.seen.size();
            n1.al.get(n1.left()).cnt+=c;
            merge(n1,n2);
        }

        for(Edge e1 : e)
        {
            System.out.print(e1.cnt+" ");
        }
        System.out.println();
    }

    private static void merge(Node n1, Node n2)
    {
        Node l=n2,r=n1;
        if(n1.seen.size() > n2.seen.size())
        {
            l = n1;
            r = n2;
        }
        Set<Integer> res = l.seen;
        for(int i : r.seen)
        {
            if(res.contains(i))
            {
                res.remove(i);
            }
            else
            {
                res.add(i);
            }
        }
        n2.seen = res;
    }

    private static class Edge
    {
        int f;
        int t;
        int cnt;
        public Edge(int f, int t)
        {
            super();
            this.f = f;
            this.t = t;
        }
    }

    private static class Node implements Comparable<Node>
    {

        int id;
        Set<Integer>seen = new HashSet<Integer>();
        Map<Integer,Edge> al = new HashMap<Integer,Edge>();

        public Node(int id)
        {
            super();
            this.id = id;
        }

        public int left()
        {
            int z = al.keySet().iterator().next();
            return z;
        }

        public int compareTo(Node arg0)
        {
            if(al.size() == arg0.al.size())
            {
                return id - arg0.id;
            }
            return al.size() - arg0.al.size();
        }

        @Override
        public boolean equals(Object obj)
        {
            if(obj == this) return true;
            if( !(obj instanceof Node)) return false;
            Node n = (Node)obj;
            return n.id == id;
        }
    }

}


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;
import java.util.Map.Entry;

public class e121_FASTER {

    public static void debug(Object... obs)
    {
        System.out.println(Arrays.deepToString(obs));
    }

    static Node[]ns;
    static Edge[]e;

    public static void main(String[] args) throws Exception
    {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st=new StringTokenizer(br.readLine());

        int n=Integer.parseInt(st.nextToken());
        ns=new Node[n];
        e=new Edge[n-1];
        for(int i=0;i<n;i++)
            ns[i]=new Node(i);
        for(int i=0;i<n-1;i++)
        {
            st=new StringTokenizer(br.readLine());
            int a=Integer.parseInt(st.nextToken())-1;
            int b=Integer.parseInt(st.nextToken())-1;

            e[i]=new Edge();
            ns[a].al.put(b,e[i]);
            ns[b].al.put(a,e[i]);
        }

        int k=Integer.parseInt(br.readLine());
        for(int i=0;i<k;i++)
        {
            st=new StringTokenizer(br.readLine());
            int a=Integer.parseInt(st.nextToken())-1;
            int b=Integer.parseInt(st.nextToken())-1;

            if(a==b) continue;

            ns[a].seen.add(i);
            ns[b].seen.add(i);
        }

        go(0, 0);

        for(Edge e1 : e)
        {
            System.out.print(e1.cnt+" ");
        }
        System.out.println();
    }

    private static Set<Integer> go(int i, int from)
    {
        Node n=ns[i];

        Set<Integer> seen = n.seen;

        for(Entry<Integer, Edge> ze : n.al.entrySet())
        {
            Integer k = ze.getKey();
            if(k.equals(from)) continue;

            Set<Integer> fm = go(k,i);
            //debug(i+1,k+1,fm.size());
            ze.getValue().cnt+=fm.size();

            seen = merge(fm,seen);
        }

        return seen;
    }

    private static Set<Integer> merge(Set<Integer> n1, Set<Integer> n2)
    {
        Set<Integer> l=n2,r=n1;
        if(n1.size() > n2.size())
        {
            l = n1;
            r = n2;
        }
        Set<Integer> res = l;
        for(Integer i : r)
        {
            if(res.contains(i))
            {
                res.remove(i);
            }
            else
            {
                res.add(i);
            }
        }
        return res;
    }

    private static class Edge
    {

        int cnt;

    }

    private static class Node implements Comparable<Node>
    {

        int id;
        Set<Integer>seen = new HashSet<Integer>();
        Map<Integer,Edge> al = new HashMap<Integer,Edge>();

        public Node(int id)
        {
            super();
            this.id = id;
        }

        public int compareTo(Node arg0)
        {
            if(al.size() == arg0.al.size())
            {
                return id - arg0.id;
            }
            return al.size() - arg0.al.size();
        }
    }

}


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

public class TaskE {
	final int MAXLOG = 31;
	int n, timer = 0;
	int[] tin, tout, ans, totalAns;
	int[][] up;
	ArrayList<Edge>[] adj;

	void dfs(int u, int anc) {
		tin[u] = ++timer;
		up[u][0] = anc;
		for (int i = 1; i < MAXLOG; i++) {
			if (up[u][i - 1] == 0) {
				break;
			}
			up[u][i] = up[up[u][i - 1]][i - 1];
		}
		for (int i = 0; i < adj[u].size(); i++) {
			if (anc != adj[u].get(i).to) {
				dfs(adj[u].get(i).to, u);
			}
		}
		tout[u] = ++timer;
	}

	int dfsAns(int u, int anc) {
		int sum = ans[u];
		for (int i = 0; i < adj[u].size(); i++) {
			if (adj[u].get(i).to != anc) {
				int tmp = dfsAns(adj[u].get(i).to, u);
				totalAns[adj[u].get(i).id] = tmp;
				sum += tmp;
			}
		}
		return sum;
	}

	boolean isUpper(int u, int v) {
		if (tin[u] <= tin[v] && tout[v] <= tout[u]) {
			return true;
		}
		return false;
	}

	int lca(int u, int v) {
		if (isUpper(u, v)) {
			return u;
		}
		if (isUpper(v, u)) {
			return v;
		}
		for (int i = MAXLOG - 1; i >= 0; i--) {
			if (!isUpper(up[u][i], v)) {
				u = up[u][i];
			}
		}
		return up[u][0];

	}

	class Edge {
		int to, id;

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

	void solve() throws IOException {
		n = nextInt();
		adj = new ArrayList[n];
		tout = new int[n];
		tin = new int[n];
		up = new int[n][MAXLOG];
		for (int i = 0; i < n; i++) {
			adj[i] = new ArrayList<Edge>();
			for (int j = 0; j < MAXLOG; j++) {
				up[i][j] = 0;
			}
		}
		for (int i = 0; i < n - 1; i++) {
			int u = nextInt() - 1, v = nextInt() - 1;
			adj[u].add(new Edge(v, i));
			adj[v].add(new Edge(u, i));
		}
		dfs(0, 0);
		int m = nextInt();
		ans = new int[n];
		for (int i = 0; i < m; i++) {
			int u = nextInt() - 1, v = nextInt() - 1;
			int curLca = lca(u, v);
			ans[u]++;
			ans[v]++;
			ans[curLca] -= 2;
		}
		totalAns = new int[n - 1];
		dfsAns(0, 0);
		for (int i = 0; i < n - 1; i++) {
			out.print(totalAns[i] + " ");
		}
	}

	void run() throws IOException {
		// br = new BufferedReader(new FileReader("input.txt"));
		// out = new PrintWriter("output.txt");
		br = new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(System.out);
		solve();
		br.close();
		out.close();
	}

	BufferedReader br;
	PrintWriter out;
	StringTokenizer stok;

	String nextToken() throws IOException {
		while (stok == null || !stok.hasMoreTokens()) {
			String s = br.readLine();
			if (s == null) {
				return null;
			}
			stok = new StringTokenizer(s);
		}
		return stok.nextToken();
	}

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

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

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

	char nextChar() throws IOException {
		return (char) (br.read());
	}

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

	public static void main(String[] args) throws IOException {
		// Locale.setDefault(Locale.US);
		new TaskE().run();
	}
}


import java.awt.Point;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.InputMismatchException;
import java.util.LinkedList;

public class R121_D1_C {

    // parent of the root (0) is itself (0);
    // root is always heavy
    // heavy[node] represent that edge reaching this node is heavy

    static int[] parent;
    static int[] chain;
    static int n;
    static int[] size;
    static LinkedList<Point> edges[];
    static boolean[] heavy;
    static int[] depth;
    static int[] res;
    static int[] oo;

    public static void dfs(int node, int d) {
        depth[node] = d;
        size[node] = 1;
        chain[node] = node;
        for (Point edge : edges[node]) {
            if (size[edge.x] == 0) {
                dfs(edge.x, d + 1);
                size[node] += size[edge.x];
                parent[edge.x] = node;
            }
        }

        for (Point edge : edges[node]) {
            // to avoid edge to ur parent.
            if (parent[edge.x] == node && size[edge.x] * 2 > size[node]) {
                heavy[edge.x] = true;
            }
        }
    }

    public static void hld(int node) {
        chain[node] = heavy[node] ? chain[parent[node]] : node;
        for (Point edge : edges[node]) {
            if (parent[edge.x] == node) {
                hld(edge.x);
            }
        }
    }

    public static int lca(int a, int b) {
        while (chain[a] != chain[b]) {
            if (depth[chain[a]] < depth[chain[b]]) {
                b = parent[chain[b]];
            } else {
                a = parent[chain[a]];
            }
        }
        return depth[a] < depth[b] ? a : b;
    }

    public static int call(int node) {
        int r = res[node];
        for (Point edge : edges[node]) {
            if (parent[edge.x] == node) {
                r += oo[edge.y] = call(edge.x);
            }
        }
        return r;
    }

    public static void precompute() {
        chain = new int[n];
        size = new int[n];
        depth = new int[n];
        heavy = new boolean[n];
        parent = new int[n];
        dfs(0, 0);
    }

    public static void main(String[] args) throws Exception {
        InputReader in = new InputReader(System.in);
        PrintWriter out = new PrintWriter(System.out);
        n = in.readInt();
        edges = new LinkedList[n];
        for (int i = 0; i < n; i++) {
            edges[i] = new LinkedList<Point>();
        }
        for (int i = 0; i < n - 1; i++) {
            int a = in.readInt() - 1;
            int b = in.readInt() - 1;
            edges[a].add(new Point(b, i));
            edges[b].add(new Point(a, i));
        }
        precompute();
        int q = in.readInt();
        res = new int[n];
        oo = new int[n - 1];
        for (int i = 0; i < q; i++) {
            int a = in.readInt() - 1;
            int b = in.readInt() - 1;
            res[a]++;
            res[b]++;
            res[lca(a, b)] -= 2;
        }
        call(0);
        for (int i = 0; i < n - 1; i++) {
            out.println(oo[i]);
        }
        out.flush();
        out.close();
    }

    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1000];
        private int curChar, numChars;

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

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

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

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

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

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

        private String readLine0() {
            StringBuffer buf = new StringBuffer();
            int c = read();
            while (c != '\n' && c != -1) {
                buf.appendCodePoint(c);
                c = read();
            }
            return buf.toString();
        }

        public String readLine() {
            String s = readLine0();
            while (s.trim().length() == 0)
                s = readLine0();
            return s;
        }

        public String readLine(boolean ignoreEmptyLines) {
            if (ignoreEmptyLines)
                return readLine();
            else
                return readLine0();
        }

        public char readCharacter() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            return (char) c;
        }

        public double readDouble() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            double res = 0;
            while (!isSpaceChar(c) && c != '.') {
                if (c == 'e' || c == 'E')
                    return res * Math.pow(10, readInt());
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            }
            if (c == '.') {
                c = read();
                double m = 1;
                while (!isSpaceChar(c)) {
                    if (c == 'e' || c == 'E')
                        return res * Math.pow(10, readInt());
                    if (c < '0' || c > '9')
                        throw new InputMismatchException();
                    m /= 10;
                    res += (c - '0') * m;
                    c = read();
                }
            }
            return res * sgn;
        }
    }

}


import java.awt.Point;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.InputMismatchException;
import java.util.LinkedList;

public class R121_D1_C {

    // parent of the root (0) is itself (0);
    // root is always heavy
    // heavy[node] represent that edge reaching this node is heavy

    static int[] parent;
    static int[] chain;
    static int n;
    static int[] size;
    static LinkedList<Point> edges[];
    static boolean[] heavy;
    static int[] depth;
    static int[] res;
    static int[] oo;

    public static void dfs(int node, int d) {
        depth[node] = d;
        size[node] = 1;
        chain[node] = node;
        for (Point edge : edges[node]) {
            if (size[edge.x] == 0) {
                dfs(edge.x, d + 1);
                size[node] += size[edge.x];
                parent[edge.x] = node;
            }
        }

        for (Point edge : edges[node]) {
            // to avoid edge to ur parent.
            if (parent[edge.x] == node && size[edge.x] * 2 > size[node]) {
                heavy[edge.x] = true;
            }
        }
    }

    public static void hld(int node) {
        chain[node] = heavy[node] ? chain[parent[node]] : node;
        for (Point edge : edges[node]) {
            if (parent[edge.x] == node) {
                hld(edge.x);
            }
        }
    }

    public static int lca(int a, int b) {
        while (chain[a] != chain[b]) {
            if (depth[chain[a]] < depth[chain[b]]) {
                b = parent[chain[b]];
            } else {
                a = parent[chain[a]];
            }
        }
        return depth[a] < depth[b] ? a : b;
    }

    public static int call(int node) {
        int r = res[node];
        for (Point edge : edges[node]) {
            if (parent[edge.x] == node) {
                r += oo[edge.y] = call(edge.x);
            }
        }
        return r;
    }

    public static void precompute() {
        chain = new int[n];
        size = new int[n];
        depth = new int[n];
        heavy = new boolean[n];
        parent = new int[n];
        dfs(0, 0);
        hld(0);
    }

    public static void main(String[] args) throws Exception {
        InputReader in = new InputReader(System.in);
        PrintWriter out = new PrintWriter(System.out);
        n = in.readInt();
        edges = new LinkedList[n];
        for (int i = 0; i < n; i++) {
            edges[i] = new LinkedList<Point>();
        }
        for (int i = 0; i < n - 1; i++) {
            int a = in.readInt() - 1;
            int b = in.readInt() - 1;
            edges[a].add(new Point(b, i));
            edges[b].add(new Point(a, i));
        }
        precompute();
        int q = in.readInt();
        res = new int[n];
        oo = new int[n - 1];
        for (int i = 0; i < q; i++) {
            int a = in.readInt() - 1;
            int b = in.readInt() - 1;
            res[a]++;
            res[b]++;
            res[lca(a, b)] -= 2;
        }
        call(0);
        for (int i = 0; i < n - 1; i++) {
            out.println(oo[i]);
        }
        out.flush();
        out.close();
    }

    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1000];
        private int curChar, numChars;

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

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

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

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

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

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

        private String readLine0() {
            StringBuffer buf = new StringBuffer();
            int c = read();
            while (c != '\n' && c != -1) {
                buf.appendCodePoint(c);
                c = read();
            }
            return buf.toString();
        }

        public String readLine() {
            String s = readLine0();
            while (s.trim().length() == 0)
                s = readLine0();
            return s;
        }

        public String readLine(boolean ignoreEmptyLines) {
            if (ignoreEmptyLines)
                return readLine();
            else
                return readLine0();
        }

        public char readCharacter() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            return (char) c;
        }

        public double readDouble() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            double res = 0;
            while (!isSpaceChar(c) && c != '.') {
                if (c == 'e' || c == 'E')
                    return res * Math.pow(10, readInt());
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            }
            if (c == '.') {
                c = read();
                double m = 1;
                while (!isSpaceChar(c)) {
                    if (c == 'e' || c == 'E')
                        return res * Math.pow(10, readInt());
                    if (c < '0' || c > '9')
                        throw new InputMismatchException();
                    m /= 10;
                    res += (c - '0') * m;
                    c = read();
                }
            }
            return res * sgn;
        }
    }

}


import java.awt.Point;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.InputMismatchException;
import java.util.LinkedList;

public class R121_D1_C {

    // parent of the root (0) is itself (0);
    // root is always heavy
    // heavy[node] represent that edge reaching this node is heavy

    static int[] parent;
    static int[] chain;
    static int n;
    static int[] size;
    static LinkedList<Point> edges[];
    static boolean[] heavy;
    static int[] depth;
    static int[] res;
    static int[] oo;

    public static void dfs(int node, int d) {
        depth[node] = d;
        size[node] = 1;
        chain[node] = node;
        for (Point edge : edges[node]) {
            if (size[edge.x] == 0) {
                dfs(edge.x, d + 1);
                size[node] += size[edge.x];
                parent[edge.x] = node;
            }
        }

        for (Point edge : edges[node]) {
            // to avoid edge to ur parent.
            if (parent[edge.x] == node && size[edge.x] * 2 >= size[node]) {
                heavy[edge.x] = true;
            }
        }
    }

    public static void hld(int node) {
        chain[node] = heavy[node] ? chain[parent[node]] : node;
        for (Point edge : edges[node]) {
            if (parent[edge.x] == node) {
                hld(edge.x);
            }
        }
    }

    public static int lca(int a, int b) {
        while (chain[a] != chain[b]) {
            if (depth[chain[a]] < depth[chain[b]]) {
                b = parent[chain[b]];
            } else {
                a = parent[chain[a]];
            }
        }
        return depth[a] < depth[b] ? a : b;
    }

    public static int call(int node) {
        int r = res[node];
        for (Point edge : edges[node]) {
            if (parent[edge.x] == node) {
                r += oo[edge.y] = call(edge.x);
            }
        }
        return r;
    }

    public static void precompute() {
        chain = new int[n];
        size = new int[n];
        depth = new int[n];
        heavy = new boolean[n];
        parent = new int[n];
        dfs(0, 0);
    }

    public static void main(String[] args) throws Exception {
        InputReader in = new InputReader(System.in);
        PrintWriter out = new PrintWriter(System.out);
        n = in.readInt();
        edges = new LinkedList[n];
        for (int i = 0; i < n; i++) {
            edges[i] = new LinkedList<Point>();
        }
        for (int i = 0; i < n - 1; i++) {
            int a = in.readInt() - 1;
            int b = in.readInt() - 1;
            edges[a].add(new Point(b, i));
            edges[b].add(new Point(a, i));
        }
        precompute();
        int q = in.readInt();
        res = new int[n];
        oo = new int[n - 1];
        for (int i = 0; i < q; i++) {
            int a = in.readInt() - 1;
            int b = in.readInt() - 1;
            res[a]++;
            res[b]++;
            res[lca(a, b)] -= 2;
        }
        call(0);
        for (int i = 0; i < n - 1; i++) {
            out.println(oo[i]);
        }
        out.flush();
        out.close();
    }

    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1000];
        private int curChar, numChars;

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

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

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

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

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

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

        private String readLine0() {
            StringBuffer buf = new StringBuffer();
            int c = read();
            while (c != '\n' && c != -1) {
                buf.appendCodePoint(c);
                c = read();
            }
            return buf.toString();
        }

        public String readLine() {
            String s = readLine0();
            while (s.trim().length() == 0)
                s = readLine0();
            return s;
        }

        public String readLine(boolean ignoreEmptyLines) {
            if (ignoreEmptyLines)
                return readLine();
            else
                return readLine0();
        }

        public char readCharacter() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            return (char) c;
        }

        public double readDouble() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            double res = 0;
            while (!isSpaceChar(c) && c != '.') {
                if (c == 'e' || c == 'E')
                    return res * Math.pow(10, readInt());
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            }
            if (c == '.') {
                c = read();
                double m = 1;
                while (!isSpaceChar(c)) {
                    if (c == 'e' || c == 'E')
                        return res * Math.pow(10, readInt());
                    if (c < '0' || c > '9')
                        throw new InputMismatchException();
                    m /= 10;
                    res += (c - '0') * m;
                    c = read();
                }
            }
            return res * sgn;
        }
    }

}


import java.awt.Point;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.InputMismatchException;
import java.util.LinkedList;

public class R121_D1_C {

    // parent of the root (0) is itself (0);
    // root is always heavy
    // heavy[node] represent that edge reaching this node is heavy

    static int[] parent;
    static int[] chain;
    static int n;
    static int[] size;
    static LinkedList<Point> edges[];
    static boolean[] heavy;
    static int[] depth;
    static int[] res;
    static int[] oo;

    public static void dfs(int node, int d) {
        depth[node] = d;
        size[node] = 1;
        chain[node] = node;
        for (Point edge : edges[node]) {
            if (size[edge.x] == 0) {
                dfs(edge.x, d + 1);
                size[node] += size[edge.x];
                parent[edge.x] = node;
            }
        }

        for (Point edge : edges[node]) {
            // to avoid edge to ur parent.
            if (parent[edge.x] == node && size[edge.x] * 2 > size[node]) {
                heavy[edge.x] = true;
            }
        }
    }

    public static void hld(int node) {
        chain[node] = heavy[node] ? chain[parent[node]] : node;
        for (Point edge : edges[node]) {
            if (parent[edge.x] == node) {
                hld(edge.x);
            }
        }
    }

    public static int lca(int a, int b) {
        while (chain[a] != chain[b]) {
            if (depth[chain[a]] < depth[chain[b]]) {
                b = parent[chain[b]];
            } else {
                a = parent[chain[a]];
            }
        }
        return depth[a] < depth[b] ? a : b;
    }

    public static int call(int node) {
        int r = res[node];
        for (Point edge : edges[node]) {
            if (parent[edge.x] == node) {
                oo[edge.y] = call(edge.x);
                r += oo[edge.y];
            }
        }
        return r;
    }

    public static void precompute() {
        chain = new int[n];
        size = new int[n];
        depth = new int[n];
        heavy = new boolean[n];
        parent = new int[n];
        dfs(0, 0);
    }

    public static void main(String[] args) throws Exception {
        InputReader in = new InputReader(System.in);
        PrintWriter out = new PrintWriter(System.out);
        n = in.readInt();
        edges = new LinkedList[n];
        for (int i = 0; i < n; i++) {
            edges[i] = new LinkedList<Point>();
        }
        for (int i = 0; i < n - 1; i++) {
            int a = in.readInt() - 1;
            int b = in.readInt() - 1;
            edges[a].add(new Point(b, i));
            edges[b].add(new Point(a, i));
        }
        precompute();
        int q = in.readInt();
        res = new int[n];
        oo = new int[n - 1];
        for (int i = 0; i < q; i++) {
            int a = in.readInt() - 1;
            int b = in.readInt() - 1;
            res[a]++;
            res[b]++;
            res[lca(a, b)] -= 2;
        }
        call(0);
        for (int i = 0; i < n - 1; i++) {
            System.out.print(oo[i]+" ");
        }
    }

    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1000];
        private int curChar, numChars;

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

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

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

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

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

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

        private String readLine0() {
            StringBuffer buf = new StringBuffer();
            int c = read();
            while (c != '\n' && c != -1) {
                buf.appendCodePoint(c);
                c = read();
            }
            return buf.toString();
        }

        public String readLine() {
            String s = readLine0();
            while (s.trim().length() == 0)
                s = readLine0();
            return s;
        }

        public String readLine(boolean ignoreEmptyLines) {
            if (ignoreEmptyLines)
                return readLine();
            else
                return readLine0();
        }

        public char readCharacter() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            return (char) c;
        }

        public double readDouble() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            double res = 0;
            while (!isSpaceChar(c) && c != '.') {
                if (c == 'e' || c == 'E')
                    return res * Math.pow(10, readInt());
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            }
            if (c == '.') {
                c = read();
                double m = 1;
                while (!isSpaceChar(c)) {
                    if (c == 'e' || c == 'E')
                        return res * Math.pow(10, readInt());
                    if (c < '0' || c > '9')
                        throw new InputMismatchException();
                    m /= 10;
                    res += (c - '0') * m;
                    c = read();
                }
            }
            return res * sgn;
        }
    }

}


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

public class tt {

    // parent of the root (0) is itself (0);
    // root is always heavy
    // heavy[node] represent that edge reaching this node is heavy

    static int[] parent;
    static int[] chain;
    static int n;
    static int[] size;
    static LinkedList<Integer> edges[];
    static ArrayList<Integer> indexes[];

    static boolean[] heavy;
    static int[] depth;
    static int[] res;
    static int[] oo;

    public static void dfs(int node, int d) {
        depth[node] = d;
        size[node] = 1;
        chain[node] = node;
        for (int edge : edges[node]) {
            if (size[edge] == 0) {
                dfs(edge, d + 1);
                size[node] += size[edge];
                parent[edge] = node;
            }
        }

        for (int edge : edges[node]) {
            // to avoid edge to ur parent.
            if (parent[edge] == node && size[edge] * 2 > size[node]) {
                heavy[edge] = true;
            }
        }
    }

    public static void hld(int node) {
        chain[node] = heavy[node] ? chain[parent[node]] : node;
        for (int edge : edges[node]) {
            if (parent[edge] == node) {
                hld(edge);
            }
        }
    }

    public static int lca(int a, int b) {
        while (chain[a] != chain[b]) {
            if (depth[chain[a]] < depth[chain[b]]) {
                b = parent[chain[b]];
            } else {
                a = parent[chain[a]];
            }
        }
        return depth[a] < depth[b] ? a : b;
    }

    public static int call(int node) {
        int r = res[node];
        int i = 0;
        for (int edge : edges[node]) {
            if (parent[edge] == node) {
                r += oo[indexes[node].get(i)] = call(edge);
            }
            i++;
        }
        return r;
    }

    public static void precompute() {
        chain = new int[n];
        size = new int[n];
        depth = new int[n];
        heavy = new boolean[n];
        parent = new int[n];
        dfs(0, 0);
    }

    public static void main(String[] args) throws Exception {
        InputReader in = new InputReader(System.in);
        PrintWriter out = new PrintWriter(System.out);
        n = in.readInt();
        edges = new LinkedList[n];
        indexes = new ArrayList[n];

        for (int i = 0; i < n; i++) {
            edges[i] = new LinkedList<Integer>();
            indexes[i] = new ArrayList<Integer>();
        }
        for (int i = 0; i < n - 1; i++) {
            int a = in.readInt() - 1;
            int b = in.readInt() - 1;
            edges[a].add(b);
            indexes[a].add(i);
            edges[b].add(a);
            indexes[b].add(i);
        }
        precompute();
        int q = in.readInt();
        res = new int[n];
        oo = new int[n - 1];
        for (int i = 0; i < q; i++) {
            int a = in.readInt() - 1;
            int b = in.readInt() - 1;
            res[a]++;
            res[b]++;
            res[lca(a, b)] -= 2;
        }
        call(0);
        for (int i = 0; i < n - 1; i++) {
            out.println(oo[i]);
        }
        out.flush();
        out.close();
    }

    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1000];
        private int curChar, numChars;

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

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

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

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

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

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

        private String readLine0() {
            StringBuffer buf = new StringBuffer();
            int c = read();
            while (c != '\n' && c != -1) {
                buf.appendCodePoint(c);
                c = read();
            }
            return buf.toString();
        }

        public String readLine() {
            String s = readLine0();
            while (s.trim().length() == 0)
                s = readLine0();
            return s;
        }

        public String readLine(boolean ignoreEmptyLines) {
            if (ignoreEmptyLines)
                return readLine();
            else
                return readLine0();
        }

        public char readCharacter() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            return (char) c;
        }

        public double readDouble() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            double res = 0;
            while (!isSpaceChar(c) && c != '.') {
                if (c == 'e' || c == 'E')
                    return res * Math.pow(10, readInt());
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            }
            if (c == '.') {
                c = read();
                double m = 1;
                while (!isSpaceChar(c)) {
                    if (c == 'e' || c == 'E')
                        return res * Math.pow(10, readInt());
                    if (c < '0' || c > '9')
                        throw new InputMismatchException();
                    m /= 10;
                    res += (c - '0') * m;
                    c = read();
                }
            }
            return res * sgn;
        }
    }

}