[AT2148] [arc063_c] Integers on a Tree
题目链接
AtCoder:https://arc063.contest.atcoder.jp/tasks/arc063_c
洛谷:https://www.luogu.org/problemnew/show/AT2148
Solution
注意到每次只能加一或减一,也就是奇偶性一定会变,那么我们可以黑白染色一波判无解。
对于权值我们直接对每个点记\(l[i],r[i]\)表示当前点可以取到的范围。
那么我们\(\rm dfs\)一边在回溯和下传的时候都更新下判无解就好了。
如果有解直接在范围内随便设值就好了。
#include<bits/stdc++.h>
using namespace std;
void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}
void print(int x) {
if(x<0) putchar('-'),x=-x;
if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}
#define lf double
#define ll long long
#define end puts("No"),exit(0)
const int maxn = 1e5+10;
const int inf = 1e9;
const lf eps = 1e-8;
int l[maxn],r[maxn],head[maxn],tot,vis[maxn],n,m,col[maxn],rt,val[maxn];
struct edge{int to,nxt;}e[maxn<<1];
void add(int u,int v) {e[++tot]=(edge){v,head[u]},head[u]=tot;}
void ins(int u,int v) {add(u,v),add(v,u);}
void dfs(int x,int fa,int c) {
if(vis[x]&&c!=col[x]) end;
if(vis[x]&&fa&&(l[x]<l[fa]-1||r[x]>r[fa]+1)) end;
if(!vis[x]) l[x]=l[fa]-1,r[x]=r[fa]+1,col[x]=c;
for(int v,i=head[x];i;i=e[i].nxt)
if((v=e[i].to)!=fa) {
dfs(v,x,c^1);
l[x]=max(l[x],l[v]-1);
r[x]=min(r[x],r[v]+1);
}
if(l[x]>r[x]) end;
}
void dfs2(int x,int fa) {
if(!fa) val[x]=l[x];
else if(val[fa]-1>=l[x]) val[x]=val[fa]-1;
else val[x]=val[fa]+1;
for(int v,i=head[x];i;i=e[i].nxt) if((v=e[i].to)!=fa) dfs2(v,x);
}
int main() {
read(n);for(int i=1,x,y;i<n;i++) read(x),read(y),ins(x,y);
read(m);
for(int i=1,x,y;i<=m;i++) {
read(x),read(y);if(i==1) rt=x;
col[x]=abs(y)&1;l[x]=r[x]=y;vis[x]=1;
}
dfs(rt,0,col[rt]);
dfs2(rt,0);
puts("Yes");for(int i=1;i<=n;i++) write(val[i]);
return 0;
}