import std.stdio;
import std.conv, std.array, std.algorithm, std.string;
import std.math, std.random, std.range, std.datetime;
import std.bigint;

class Node{
	Node[] adjnodes;
	int _value;
	bool hasValue = false;
	int color = 0; // 0: undef, 1: black, 2: white
	int min = 0, max = 1_000_000;
	int isDeadend = false;
	static hasError = false;
	this(){
		}
	void add(Node nd){
		this.adjnodes ~= nd;
		nd.adjnodes ~= this;
		}
	void setColor(int c){
		if(this.color > 0) return;
		this.color = c;
		foreach(nd; adjnodes) nd.setColor(1 + 2 - c);
		}
	int value(int v){
		this._value = v;
		this.hasValue = 1;
		return _value;
		}
	int value(){	
		return _value;
		}
	void markEnd(){
		if(this.hasValue) return;
		else if(this.adjnodes.length > 1) return;
		this.isDeadend = true;
		Node nd = this.adjnodes[0];
		while(1){
			if(nd.adjnodes.length != 2) break;
			if(nd.hasValue) break;
			nd.isDeadend = true;
			if(!nd.adjnodes[0].isDeadend) nd = nd.adjnodes[0];
			else if(!nd.adjnodes[1].isDeadend) nd = nd.adjnodes[1];
			else break;
			}
		}
	void start(){
		Node[] q;
		foreach(nd; this.adjnodes) q ~= [this, nd];
		while(q.length){
			Node nd0, nd;
			nd0 = q[0], q = q[1 .. $];
			nd = q[0], q = q[1 .. $];
//			if(nd.isDeadend) continue;
			if(nd.min < nd0.min - 1 || nd.max > nd0.max + 1){
				if(nd.min > nd0.max + 1 || nd.max < nd0.min - 1){
					hasError = true;
					return;
					}
				nd.min = nd0.min - 1, nd.max = nd0.max + 1;
				foreach(nd2; nd.adjnodes) q ~= [nd, nd2];
				}
			}
		}
	string toString(){
		return (isDeadend? "*": " ") ~ adjnodes.length.to!string ~ (hasValue? ("(" ~ value.to!string ~ ")"): "");
		}
	}

void main(){
	int n = readln.chomp.to!int;
	
	Node[] nodes;
	foreach(i; 0 .. n) nodes ~= new Node;
	foreach(i; 0 .. n - 1){
		int[] tmp = readln.chomp.split.map!(to!int).map!(x => x - 1).array;
		nodes[tmp[0]].add(nodes[tmp[1]]);
		}
	
	Node[] valuednodes;
	int k = readln.chomp.to!int;
	foreach(i; 0 .. k){
		int[] tmp = readln.chomp.split.map!(to!int).array;
		tmp[0] -= 1;
		nodes[tmp[0]].value = tmp[1];
		valuednodes ~= nodes[tmp[0]];
		}
	
	valuednodes[0].setColor((valuednodes[0].value % 2)? 1: 2);
	foreach(nd; valuednodes) if(nd.color != ((nd.value % 2)? 1: 2)){
		"No".writeln;
		return;
		}
	
	foreach(nd; nodes) nd.markEnd;
	
	foreach(nd; valuednodes){
		if(nd.min > nd.value){
			"No".writeln;
			return;
			}
		if(nd.max < nd.value){
			"No".writeln;
			return;
			}
		nd.min = nd.value, nd.max = nd.value;
		nd.start;
		if(Node.hasError){
			"No".writeln;
			return;
			}
		}
	
	foreach(nd; nodes) nd.max.writeln;
	
	debug nodes.writeln;
	
	}




/*

①偶奇でおかしくなっていないかチェックしておかしかったらNo

②偶奇はいいとして、
・各数字の入っているマスについて以下のことをする
	最大値と最小値がすでに入っている場合、範囲外ならNo
	最大値と最小値をその数字の値にセットする
	数字を消す
	隣のマスについて
		自分の最大値＋１、自分の最小値－１をそこの最大値、最小値とする
		最大値と最小値がすでにセットされていれば共通部分とする
			共通部分がなければNo
		数字が入っているマスだった場合はストップ
		数字が入っていないマスだった場合はそこから更に隣のマスへ
	そのマスを処理済とする
*/
