using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;

using Pair = System.Collections.Generic.KeyValuePair<int, int>;

class Program
{
	public Program() { }

	static void Main(string[] args)
	{
		new Program().prog();
	}
	Scanner cin;
	const int MOD = 1000000007;
	const int INF = int.MaxValue - 10;
	const long INFL = long.MaxValue - 10;
	const double EPS = 1e-7;
	const double PI = 3.1415926536;

	List<int>[] G;
	int N;
	int[] num;
	int[,] range;
	int root = 0;

	void prog()
	{
		cin = new Scanner();
		int[,] dir8 = new int[8, 2] { { -1, -1 }, { -1, 0 }, { -1, 1 }, { 0, -1 }, { 0, 1 }, { 1, -1 }, { 1, 0 }, { 1, 1 } };
		int[,] dir4 = new int[4, 2] { { -1, 0 }, { 0, -1 }, { 0, 1 }, { 1, 0 } };

		N = cin.nextInt();
		G = new List<int>[N];	// グラフの隣接リスト
		num = new int[N];		// 各ノードに書き込む数字（空白は-1）
		range = new int[N, 2];	// 各ノードに書き込む数字の許容範囲（自由な場合は[-INF,INF]）

		// 初期化
		for (int i = 0; i < N; i++)
		{
			G[i] = new List<int>();
			num[i] = -1;		// 全ノードの数字を-1で初期化
		}

		// 入力受け取り
		for (int i = 0; i < N - 1; i++)
		{
			int A = cin.nextInt() - 1;
			int B = cin.nextInt() - 1;
			G[A].Add(B);
			G[B].Add(A);
		}
		int K = cin.nextInt();
		for (int i = 0; i < K; i++)
		{
			int V = cin.nextInt() - 1;
			int P = cin.nextInt();
			num[V] = P;
			root = V;	// 数字が書かれたノードを根ノードに設定
		}

		// 各ノードの許容範囲を計算
		if (!range_set(root, -1, num[root] % 2 == 0))
		{
			Console.WriteLine("No");
			return;
		}

		// 各ノードの数字を設定
		if (!num_set(root, -1, num[root] % 2 == 0))
		{
			Console.WriteLine("No");
			return;
		}

		// 結果を表示
		Console.WriteLine("Yes");
		for (int i = 0; i < N; i++)
		{
			Console.WriteLine(num[i]);
		}
	}

	// 深さ優先探索で各ノードの許容幅を設定
	bool range_set(int pos, int parent, bool even)
	{
		int min = -INF, max = INF;

		// 深さ優先探索
		for (int i = 0; i < G[pos].Count; i++)
		{
			if (G[pos][i] == parent) continue;
			if (range_set(G[pos][i], pos, !even))
			{
				// posノードの許容範囲は子から得られる許容範囲の共通部分
				min = Math.Max(min, range[G[pos][i], 0] - 1);	// 子の数値-1まで可能
				max = Math.Min(max, range[G[pos][i], 1] + 1);	// 子の数値+1まで可能
			}
			else
			{
				// 子ノードのいずれかで条件を満たさなかったらアウト
				return false;
			}
		}

		if (num[pos] != -1)	// すでに数字が書かれていたら
		{
			// すでにある数字が許容範囲外だったらアウト
			if (num[pos] < min || max < num[pos] || (num[pos] % 2 == 0) != even)
			{
				return false;
			}
			else
			{
				// 許容範囲をすでにある数字に設定
				range[pos, 0] = num[pos];
				range[pos, 1] = num[pos];
				return true;
			}
		}
		else	// 数字が書かれていなかったら
		{
			// 許容範囲を設定
			range[pos, 0] = min;
			range[pos, 1] = max;
			return true;
		}
	}

	// 深さ優先探索で各ノードの数値を設定
	bool num_set(int pos, int parent, bool even)
	{
		// まだ数字が書かれていないノードに対して
		if (num[pos] == -1)
		{
			// 親の数字+1か親の数字-1か、可能な方を選択
			if (num[parent] + 1 >= range[pos, 0] && num[parent] + 1 <= range[pos, 1])
			{
				num[pos] = num[parent] + 1;
			}
			else if (num[parent] - 1 >= range[pos, 0] && num[parent] - 1 <= range[pos, 1])
			{
				num[pos] = num[parent] - 1;
			}
			else
			{
				// 可能なものが無ければアウト
				return false;
			}
		}
		// 深さ優先探索
		for (int i = 0; i < G[pos].Count; i++)
		{
			if (G[pos][i] == parent) continue;
			if (!num_set(G[pos][i], pos, !even)) return false;
		}
		return true;
	}
}

class Scanner
{
	string[] s;
	int i;

	char[] cs = new char[] { ' ' };

	public Scanner()
	{
		s = new string[0];
		i = 0;
	}

	public string next()
	{
		if (i < s.Length) return s[i++];
		string st = Console.ReadLine();
		while (st == "") st = Console.ReadLine();
		s = st.Split(cs, StringSplitOptions.RemoveEmptyEntries);
		i = 0;
		return next();
	}

	public int nextInt()
	{
		return int.Parse(next());
	}

	public long nextLong()
	{
		return long.Parse(next());
	}

	public double nextDouble()
	{
		return double.Parse(next());
	}
}

Measured memory_bytes: 26212