题目大意
一颗点权树,相邻节点点权差绝对值为1。
现在一些点点权已确定,构造一种方案。
做法
自下而上推出每个节点点权区间范围。
为空则无解,同时如果儿子间对该点奇偶性要求不同也无解。
然后接下来只需自上而下构造,只要和父亲相差1,且点权在区间范围内一定可以合法。
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=100000+10;
int h[maxn],go[maxn*2],nxt[maxn*2],L[maxn],R[maxn],v[maxn];
bool bz[maxn];
int i,j,k,l,t,n,m,tot;
bool czy;
void add(int x,int y){
go[++tot]=y;
nxt[tot]=h[x];
h[x]=tot;
}
void dfs(int x,int y){
int t=h[x];
while (t){
if (go[t]!=y){
dfs(go[t],x);
if (!czy) return;
bz[x]|=bz[go[t]];
}
t=nxt[t];
}
if (v[x]!=-1) bz[x]=1;
if (!bz[x]) return;
int l,r;
bool gjx=0;
if (v[x]!=-1){
gjx=1;
l=r=v[x];
}
t=h[x];
while (t){
if (go[t]!=y&&bz[go[t]]){
if (!gjx){
gjx=1;
l=L[go[t]]-1;
r=R[go[t]]+1;
}
else{
if (R[go[t]]+1<l||L[go[t]]-1>r||l%2!=(L[go[t]]-1)%2){
czy=0;
return;
}
l=max(l,L[go[t]]-1);
r=min(r,R[go[t]]+1);
}
}
t=nxt[t];
}
L[x]=l;R[x]=r;
}
void dg(int x,int y){
if (x!=1){
if (!bz[x]) v[x]=v[y]+1;
else if (L[x]<=v[y]+1&&v[y]+1<=R[x]) v[x]=v[y]+1;
else v[x]=v[y]-1;
}
int t=h[x];
while (t){
if (go[t]!=y) dg(go[t],x);
t=nxt[t];
}
}
int main(){
scanf("%d",&n);
fo(i,1,n-1){
scanf("%d%d",&j,&k);
add(j,k);add(k,j);
}
fo(i,1,n) v[i]=-1;
scanf("%d",&m);
fo(i,1,m){
scanf("%d%d",&j,&k);
v[j]=k;
}
czy=1;
dfs(1,0);
if (!czy){
printf("No\n");
return 0;
}
printf("Yes\n");
v[1]=L[1];
dg(1,0);
fo(i,1,n) printf("%d\n",v[i]);
}