#ifndef __RANGE_H__
#define __RANGE_H__

#include <utility>
#include <iterator>

#include <string>
#include <sstream>
#include <iostream>

template<class T>
struct Range {
	T inf_m;
	T sup_m;
	bool inf_inclusive_m;
	bool sup_inclusive_m;

	static Range Empty_range();
	void Reduce();

public:
	static bool Equal(const Range& left, const Range& right);
	//static bool compare(const Range& left, const Range& right);

	Range();
	Range(const T& inf, const T& sup, bool inf_inclusive = true, bool sup_inclusive = false);
	Range(const std::pair<T, T>& pair, bool inf_inclusive = true, bool sup_inclusive = false);	// T, Tでなくてもいい
	Range(const Range& other);

	Range& operator=(const Range& other);
	Range& operator&=(const Range& other);

	bool Is_empty() const;
	std::string To_string() const;
	T Width() const;

	bool Has(const T& point) const;
	bool Includes(const Range& other) const;
};

template<class T>
bool operator==(const Range<T>& left, const Range<T>& right);
template<class T>
bool operator!=(const Range<T>& left, const Range<T>& right);
template<class T>
const Range<T> operator&(const Range<T>& left, const Range<T>& right);
template<class T>
std::ostream& operator<<(std::ostream& ost, const Range<T>& range);

/* ここを Range(0, 0) とすると無限ループなので注意 */
template<class T>
inline Range<T> Range<T>::Empty_range() {
	return Range();
}

/* 空集合であったら [0, 0) の基本形に直す */
template<class T>
inline void Range<T>::Reduce() {
	if (Is_empty()) {
		*this = Empty_range();
	}
}

template<class T>
inline bool Range<T>::Equal(const Range& left, const Range& right) {
	return left.inf_m == right.inf_m
		&& left.sup_m == right.sup_m
		&& left.inf_inclusive_m == right.inf_inclusive_m
		&& left.sup_inclusive_m == right.sup_inclusive_m;
}

template<class T>
inline Range<T>::Range()
	:inf_m(0), sup_m(0), inf_inclusive_m(true), sup_inclusive_m(false) {
}

template<class T>
inline Range<T>::Range(const T& inf, const T& sup, bool inf_inclusive, bool sup_inclusive)
	: inf_m(inf), sup_m(sup), inf_inclusive_m(inf_inclusive), sup_inclusive_m(sup_inclusive) {
	Reduce();
}

template<class T>
inline Range<T>::Range(const std::pair<T, T>& pair, bool inf_inclusive, bool sup_inclusive)
	: inf_m(pair.first), sup_m(pair.second), inf_inclusive_m(inf_inclusive), sup_inclusive_m(sup_inclusive) {
	Reduce();
}

template<class T>
inline Range<T>::Range(const Range& other)
	: inf_m(other.inf_m), sup_m(other.sup_m),
	inf_inclusive_m(other.inf_inclusive_m), sup_inclusive_m(other.sup_inclusive_m) {
}

template<class T>
inline Range<T>& Range<T>::operator=(const Range& other) {
	inf_m = other.inf_m;
	sup_m = other.sup_m;
	inf_inclusive_m = other.inf_inclusive_m;
	sup_inclusive_m = other.sup_inclusive_m;
	return *this;
}

template<class T>
inline Range<T>& Range<T>::operator&=(const Range& other) {
	if (inf_m < other.inf_m || (inf_m == other.inf_m && !other.inf_inclusive_m)) {
		inf_m = other.inf_m;
		inf_inclusive_m = other.inf_inclusive_m;
	}
	if (sup_m > other.sup_m || (sup_m == other.sup_m && !other.sup_inclusive_m)) {
		sup_m = other.sup_m;
		sup_inclusive_m = other.sup_inclusive_m;
	}
	Reduce();
	return *this;
}

template<class T>
inline bool Range<T>::Is_empty() const {
	return inf_m > sup_m || (inf_m == sup_m && (!inf_inclusive_m || !sup_inclusive_m));
}

template<class T>
inline std::string Range<T>::To_string() const {
	if (Is_empty()) return "(Empty)";
	std::ostringstream sst;
	sst << (inf_inclusive_m ? '[' : '(')
		<< inf_m
		<< ", "
		<< sup_m
		<< (sup_inclusive_m ? ']' : ')');
	return sst.str();
}

template<class T>
inline T Range<T>::Width() const {
	return sup_m - inf_m;
}

template<class T>
inline bool Range<T>::Has(const T& point) const {
	return (inf_inclusive_m ? point >= inf_m : point > inf_m)
		&& (sup_inclusive_m ? point <= sup_m : point < sup_m);
}

/* other == (*this) & other の判定でもいいかも */
/* 逆の判定も使いたい */
template<class T>
inline bool Range<T>::Includes(const Range& other) const {
	if (other.Is_empty()) return true;
	return (inf_inclusive_m || !other.inf_inclusive_m ? other.inf_m >= inf_m : other.inf_m > inf_m)
		&& (sup_inclusive_m || !other.sup_inclusive_m ? other.sup_m <= sup_m : other.sup_m < sup_m);
}

template<class T>
inline bool operator==(const Range<T>& left, const Range<T>& right) {
	return Range<T>::Equal(left, right);
}

template<class T>
inline bool operator!=(const Range<T>& left, const Range<T>& right) {
	return !Range<T>::Equal(left, right);
}

template<class T>
inline const Range<T> operator&(const Range<T>& left, const Range<T>& right) {
	Range<T> ret(left);
	ret &= right;
	return ret;
}

template<class T>
inline std::ostream& operator<<(std::ostream& ost, const Range<T>& range) {
	ost << range.To_string();
	return ost;
}

typedef Range<int> RangeInt;

#endif


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <utility>
#include <algorithm>
#include <functional>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <iomanip>
#include <sstream>
#include <numeric>
#include <bitset>
#include <limits>

using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<LL, LL> PP;
#define REP(i,a,n) for(int i = (a); i < (int)(n); ++i)
#define REPM(i,n,a) for(int i = ((n) - 1); i >= (a); --i)
#define FLOAT setprecision(16)
#define INSIDE(i,j,H,W) ((i) >= 0 && (i) < (H) && (j) >= 0 && (j) < (W))
#define YesNo(b) (b ? "Yes" : "No")
#define YESNO(b) (b ? "YES" : "NO")
const int INF = 0x3FFFFFFF;
const LL INFLL = 0x3FFFFFFF3FFFFFFF;
const double INFD = 1.0e+308;
const double EPS = 1.0e-9;

template <class T, class U>
istream& operator>>(istream& ist, pair<T, U>& right) { return ist >> right.first >> right.second; }
template <class T, class U>
ostream& operator<<(ostream& ost, pair<T, U>& right) { return ost << right.first << ' ' << right.second; }
template <class T, class TCompatible, size_t N>
void Fill(T(&dest)[N], const TCompatible& val) { fill(begin(dest), end(dest), val); }
template <class T, class TCompatible, size_t M, size_t N>
void Fill(T(&dest)[M][N], const TCompatible& val) { for (int i = 0; i < M; ++i) Fill(dest[i], val); }
// all_of

#if 1234567891
#include <array>
#include <unordered_set>
#include <unordered_map>
template<typename T>
using PriorityQ = priority_queue<T, vector<T>, greater<T> >;	// コスト小を優先
#endif

#if _DEBUG
#include "IntMod.h"
#include "Union_Find.h"
#include "Graph.h"
#include "Range.h"
#endif
int P[100000];
vector<int> G[100000];
int N, K;

RangeInt R[100000];
int ans[100000];
bool ok = true;

RangeInt dfs(int i, int from) {
	RangeInt ret = (P[i] == -1 ? RangeInt(-INF, INF) : RangeInt(P[i], P[i], true, true));
	for (auto to : G[i]) {
		if (to == from) continue;
		ret &= dfs(to, i);
	}
	if (ret.Is_empty()) ok = false;
	R[i] = ret;
	ret.inf_m--; ret.sup_m++;
	return ret;
}

void dfs2(int i, int from) {
	if (from == -1) {
		ans[i] = R[i].inf_m;
	} else {
		if (P[i] == -1) {
			if (R[i].Has(ans[from] - 1)) {
				ans[i] = ans[from] - 1;
			} else {
				ans[i] = ans[from] + 1;
			}
		} else {
			if (P[i] != ans[from] + 1 && P[i] != ans[from] - 1) {
				ok = false;
				return;
			}
			ans[i] = P[i];
		}
	}
	for (auto to : G[i]) {
		if (to == from) continue;
		dfs2(to, i);
	}
}

int main() {
	cin >> N;
	REP(i, 0, N - 1) {
		int a, b;
		cin >> a >> b;
		--a; --b;
		G[a].push_back(b);
		G[b].push_back(a);
	}
	cin >> K;
	Fill(P, -1);
	REP(i, 0, K) {
		int v, p;
		cin >> v >> p;
		--v;
		P[v] = p;
	}

	dfs(0, -1);
	if (ok) {
		dfs2(0, -1);
	}

	cout << YesNo(ok) << endl;
	if (ok) {
		REP(i, 0, N) {
			cout << ans[i] << endl;
		}
	}
	return 0;
}

Measured memory_bytes: 16128