[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;
}

猜你喜欢

转载自www.cnblogs.com/hbyer/p/10708713.html