传送门
题意:
给你一颗nnn个点的树,初始的时候某些点有权值pip_ipi,现在你需要给没给定的点赋一个权值,使得任意相邻点权值之差的绝对值等于111,若无解输出NoNoNo。
1≤n≤1e5,1≤k≤n,0≤pj≤1e51\le n\le 1e5,1\le k\le n,0\le p_j\le 1e51≤n≤1e5,1≤k≤n,0≤pj≤1e5
思路:
考虑以定一个根,先递归儿子,求出儿子能取到的权值范围,让后根据儿子的范围来确定当前点的范围,不合法的话就直接输出NoNoNo即可。
如果合法的话,显然从我们之前选定的根开始随意的取一个区间内的合法值一定可以构造出答案。
#include<bits/stdc++.h>
#define X first
#define Y second
#define Mid (tr[u].l+tr[u].r>>1)
#define pb push_back
using namespace std;const int N=1000010,INF=0x3f3f3f3f,mod=1e9+7;
typedef long long LL;int n,m;
vector<int>v[N];
int a[N],col[N];
int l[N],r[N];void dfs_col(int u,int fa,int c) {col[u]=c;for(auto x:v[u]) {if(x==fa) continue;dfs_col(x,u,!c);}
}void dfs(int u,int fa) {for(auto x:v[u]) {if(x==fa) continue;dfs(x,u);l[u]=max(l[u],l[x]-1);r[u]=min(r[u],r[x]+1);}if(l[u]>r[u]) {puts("No");exit(0);}
}void dfs_ans(int u,int fa,int val) {a[u]=val;for(auto x:v[u]) {if(x==fa) continue;if(val-1>=l[x]&&val-1<=r[x]) dfs_ans(x,u,val-1);else dfs_ans(x,u,val+1);}
}void solve() {scanf("%d",&n);for(int i=1;i<=n-1;i++) {int a,b; scanf("%d%d",&a,&b);v[a].push_back(b);v[b].push_back(a);}for(int i=1;i<=n;i++) l[i]=-INF,r[i]=INF;memset(a,-1,sizeof(a));scanf("%d",&m);for(int i=1;i<=m;i++) {int aa,b; scanf("%d%d",&aa,&b);a[aa]=b;l[aa]=b; r[aa]=b;}for(int i=1;i<=n;i++) if(a[i]>=0) {dfs_col(i,0,a[i]%2);break;}for(int i=1;i<=n;i++) if(a[i]>=0&&(a[i]%2!=col[i])) {puts("No");return;}dfs(1,0);dfs_ans(1,0,l[1]);puts("Yes");for(int i=1;i<=n;i++) printf("%d\n",a[i]);puts("");
}int main() {int _=1;while(_--) {solve();}return 0;
}