思路是换根 dp,down 一次 up 一次求出每个点的取值范围,感觉很对
#include <bits/stdc++.h>
int n, k, ve[100005], p[100005];
int l[100005], r[100005], dep[100005], ans[100005];
int noot;
std::vector <int> vc[100005];
void dfs1(int x, int fa){
for(auto v : vc[x]){
if(v == fa) continue;
dep[v] = dep[x] + 1;
dfs1(v, x);
}
return ;
}
void dfs2(int x, int fa){
for(auto v : vc[x]){
if(v == fa) continue;
dfs2(v, x);
l[x] = std::max(l[x], l[v] - 1);
r[x] = std::min(r[x], r[v] + 1);
}
return ;
}
void dfs3(int x, int fa){
if(x != 1){
l[x] = std::max(l[x], l[fa] - 1);
r[x] = std::min(r[x], r[fa] + 1);
}
for(auto v : vc[x]){
if(v == fa) continue;
dfs3(v, x);
}
return ;
}
void dfs4(int x, int fa){
for(auto v : vc[x]){
if(v == fa) continue;
int nmsl = ans[x] - 1; nmsl = std::max(nmsl, l[v]);
if((nmsl ^ dep[v]) % 2 == noot) ans[v] = nmsl;
else ans[v] = nmsl + 1;
if(ans[v] > r[v]){
printf("No\n");
exit(0);
}
dfs4(v, x);
}
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n - 1; ++i){
int x, y;
scanf("%d%d", &x, &y);
vc[x].push_back(y);
vc[y].push_back(x);
}
for(int i = 1; i <= n; ++i) l[i] = -200000, r[i] = 200000;
dfs1(1, 0);
scanf("%d", &k);
for(int i = 1; i <= k; ++i) scanf("%d%d", &ve[i], &p[i]);
for(int i = 1; i <= k; ++i) l[ve[i]] = r[ve[i]] = p[i];
for(int i = 2; i <= k; ++i){
int s1 = dep[ve[i - 1]] + p[i - 1];
int s2 = dep[ve[i]] + p[i];
if(s1 % 2 != s2 % 2){
printf("No\n");
return 0;
}
}
noot = (dep[ve[1]] ^ p[1]) % 2;
dfs2(1, 0);
dfs3(1, 0);
for(int i = 1; i <= n; ++i)
if(l[i] > r[i]){
printf("No\n");
return 0;
}
printf("Yes\n");
if(l[1] % 2 == noot) ans[1] = l[1];
else ans[1] = l[1] + 1;
if(ans[1] > r[1]){
printf("No\n");
return 0;
}
dfs4(1, 0);
for(int i = 1; i <= n; ++i) printf("%d\n", ans[i]);
return 0;
}