Problem: There are n railway stations in Berland. They are connected to each other by n-1 railway sections. The railway network is connected, i.e. can be represented as an undirected tree.

You have a map of that network, so for each railway section you know which stations it connects.

Each of the n-1 sections has some integer value of the scenery beauty. However, these values are not marked on the map and you don't know them. All these values are from 1 to 10^6 inclusive.

You asked m passengers some questions: the j-th one told you three values:

  * his departure station a_j; 
  * his arrival station b_j; 
  * minimum scenery beauty along the path from a_j to b_j (the train is moving along the shortest path from a_j to b_j). 



You are planning to update the map and set some value f_i on each railway section — the scenery beauty. The passengers' answers should be consistent with these values.

Print any valid set of values f_1, f_2, ..., f_{n-1}, which the passengers' answer is consistent with or report that it doesn't exist.

Input

The first line contains a single integer n (2 ≤ n ≤ 5000) — the number of railway stations in Berland.

The next n-1 lines contain descriptions of the railway sections: the i-th section description is two integers x_i and y_i (1 ≤ x_i, y_i ≤ n, x_i ≠ y_i), where x_i and y_i are the indices of the stations which are connected by the i-th railway section. All the railway sections are bidirected. Each station can be reached from any other station by the railway.

The next line contains a single integer m (1 ≤ m ≤ 5000) — the number of passengers which were asked questions. Then m lines follow, the j-th line contains three integers a_j, b_j and g_j (1 ≤ a_j, b_j ≤ n; a_j ≠ b_j; 1 ≤ g_j ≤ 10^6) — the departure station, the arrival station and the minimum scenery beauty along his path.

Output

If there is no answer then print a single integer -1.

Otherwise, print n-1 integers f_1, f_2, ..., f_{n-1} (1 ≤ f_i ≤ 10^6), where f_i is some valid scenery beauty along the i-th railway section.

If there are multiple answers, you can print any of them.

Examples

Input


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


Output


5 3 5


Input


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


Output


5 3 1 2 1 


Input


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


Output


-1

Solution (in JAVA):

Solution:
//package com.codeforces.milindc;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Queue;
import java.util.StringTokenizer;
 
public class BerlandBeautyScanner {
	public static void main(String[] args) throws IOException {
		FastReader fr = new FastReader();
		int N = Integer.parseInt(fr.nextLine());
		int[][] adj2 = new int[N][N];
		for(int i = 0; i<N; i++) {
			for(int j = 0; j<N; j++){
				adj2[i][j] = -1;
			}
		}
		List<Integer>[] adj = new List[N];
		for (int i = 0; i < N; i++) {
			List<Integer> curr = new ArrayList<>();
			adj[i] = curr;
		}
		int[][] printOrder = new int[N][2];
		for (int i = 0; i < N - 1; i++) {
			printOrder[i] = to2Int(fr.nextLine().split(" "));
			addedge(adj, printOrder[i][0], printOrder[i][1]);
		}
		int[][] reports = new int[Integer.parseInt(fr.nextLine())][3];
		for (int i = 0; i < reports.length; i++) {
			reports[i] = to3Int(fr.nextLine().split(" "));
		}
		sortbyColumn(reports);
		List<int[]> shortestPaths = new ArrayList<>();
		for (int i = 0; i < reports.length; i++) {
//			System.out.println(reports[i][2]);
			int[] shortestPath = shortestPath(adj, reports[i][0], reports[i][1]);
//			System.out.println(Arrays.toString(shortestPath));
			shortestPaths.add(shortestPath);
			for (int j = 0; j < shortestPath.length - 1; j++) {
				int src = shortestPath[j];
				int dest = shortestPath[j + 1];
				adj2[src][dest] = reports[i][2];
				adj2[dest][src] = reports[i][2];
			}
		}
		boolean possible = true;
		for (int i = 0; i < shortestPaths.size(); i++) {
			int[] shortestPath = shortestPaths.get(i);
			int color = reports[i][2];
			boolean pathBoolean = false;
			for (int j = 0; j < shortestPath.length - 1; j++) {
				if (color == adj2[shortestPath[j]][shortestPath[j + 1]]) {
					pathBoolean = true;
					break;
				}
			}
			if (pathBoolean) {
				continue;
			} else {
				possible = false;
				break;
			}
		}
		if (!possible) {
			System.out.println("-1");
		} else {
			System.out.println(printArrays(adj2, printOrder, reports[reports.length - 1][2]));
		}
	}
 
	private static int[] to2Int(String[] tokens) {
		int[] arr = new int[tokens.length];
		arr[0] = Integer.parseInt(tokens[0]) - 1;
		arr[1] = Integer.parseInt(tokens[1]) - 1;
		return arr;
	}
 
	private static int[] to3Int(String[] tokens) {
		int[] arr = new int[tokens.length];
		arr[0] = Integer.parseInt(tokens[0]) - 1;
		arr[1] = Integer.parseInt(tokens[1]) - 1;
		arr[2] = Integer.parseInt(tokens[2]);
		return arr;
	}
 
	public static void addedge(List<Integer>[] adj, int src, int dest) {
		adj[src].add(dest);
		adj[dest].add(src);
	}
 
	public static boolean BFS(List<Integer>[] adj, int src, int dest, int v, int pred[], int dist[]) {
		Queue<Integer> queue = new ArrayDeque<>();
 
		boolean[] visited = new boolean[v];
 
		for (int i = 0; i < v; i++) {
			visited[i] = false;
			dist[i] = Integer.MAX_VALUE;
			pred[i] = -1;
		}
 
		visited[src] = true;
		dist[src] = 0;
 
		queue.add(src);
 
		while (queue.size() != 0) {
			int u = queue.remove();
			for (int i = 0; i < adj[u].size(); i++) {
				if (visited[adj[u].get(i)] == false) {
					visited[adj[u].get(i)] = true;
					dist[adj[u].get(i)] = dist[u] + 1;
					pred[adj[u].get(i)] = u;
					queue.add(adj[u].get(i));
 
					if (adj[u].get(i) == dest) {
						return true;
					}
				}
			}
		}
 
		return false;
	}
 
	public static int[] shortestPath(List<Integer> adj[], int s, int dest) {
		int v = adj.length;
		int[] pred = new int[v];
		int[] dist = new int[v];
 
		if (BFS(adj, s, dest, v, pred, dist) == false) {
			return null;
		}
 
		List<Integer> path = new ArrayList<>();
		int crawl = dest;
		path.add(crawl);
		while (pred[crawl] != -1) {
			path.add(pred[crawl]);
			crawl = pred[crawl];
		}
		int[] finalPath = new int[path.size()];
		for (int i = 0; i < finalPath.length; i++) {
			finalPath[i] = path.get(i);
		}
		reverse(finalPath);
		return finalPath;
	}
 
	public static void sortbyColumn(int arr[][]) {
		Arrays.sort(arr, new Comparator<int[]>() {
 
			@Override
			public int compare(final int[] entry1, final int[] entry2) {
 
				if (entry1[2] == entry2[2]) {
					return 0;
				}
				if (entry1[2] > entry2[2]) {
					return 1;
				} else {
					return -1;
				}
			}
		});
	}
 
	public static void reverse(int a[]) {
		int n = a.length;
		for (int i = 0; i < n / 2; i++) {
			int temp = a[i];
			a[i] = a[n - i - 1];
			a[n - i - 1] = temp;
		}
	}
 
	public static String printArrays(int[][] adj2, int[][] printOrder, int largestColor) {
		String solution = "";
		for (int i = 0; i < printOrder.length - 1; i++) {
			int src = printOrder[i][0];
			int dest = printOrder[i][1];
			if (adj2[src][dest] == -1) {
				adj2[src][dest] = largestColor;
			}
			solution += adj2[src][dest] + " ";
		}
		return solution;
	}
	
	static class FastReader {
		BufferedReader br;
		StringTokenizer st;
 
		public FastReader() {
			br = new BufferedReader(new InputStreamReader(System.in));
		}
 
		String next() {
			while (st == null || !st.hasMoreElements()) {
				try {
					st = new StringTokenizer(br.readLine());
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			return st.nextToken();
		}
 
		int nextInt() {
			return Integer.parseInt(next());
		}
 
		long nextLong() {
			return Long.parseLong(next());
		}
 
		double nextDouble() {
			return Double.parseDouble(next());
		}
 
		String nextLine() {
			String str = "";
			try {
				str = br.readLine();
			} catch (IOException e) {
				e.printStackTrace();
			}
			return str;
		}
	}
}