CodeForces - 717E Paint it really, really dark gray

Posted on 2022-01-05 13:14  Capterlliar  阅读(37)  评论(0编辑  收藏  举报

题意:给出一棵树,每个结点是黑色或者粉色。每经过一个结点一次,这个结点变一次色(一开始站在根节点时不变色)。求一条路径,沿此路径走完后整棵树变成黑色。

解:到达一个结点后需不需要往下走取决于子树中有没有粉色结点,于是先dfs一次处理子树。然后开始解,如果有粉色结点,就递归递进去。回溯在遍历完所有子树之后,如果当前节点是粉的,就走到父亲节点再走回来。注意根结点没有父亲结点,可以挑一个子节点走过去再走回来这么走两遍。

每经过一个节点变一次色,记录一下路径,这样debug的时候也方便。

其实这是道构造题吧。。。

代码:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define eps 0.00000001
#define inf 0x7fffffff
#define maxx 200005
int n;
int a[maxx]={0},son[maxx]={0};
vector<int> ans;
struct edge{int u,v,next;}e[maxx*2];int head[maxx]={0};int cnt=0;
void add(int u,int v){e[++cnt].u=u;e[cnt].v=v;e[cnt].next=head[u];head[u]=cnt;}
void dfs2(int now,int fa){
    if(son[now]==0){
        a[now]=-a[now];
        ans.push_back(now);
        return;
    }
    ans.push_back(now);
    a[now]=-a[now];
    for(int i=head[now];i;i=e[i].next){
        int to=e[i].v;
        if(to==fa)
            continue;
        if(a[to]==-1||son[to]>0) {
            dfs2(to, now);
            ans.push_back(now);
            a[now]=-a[now];
        }
    }
    if(a[now]==-1&&now!=1){
        ans.push_back(fa);
        a[fa]=-a[fa];
        ans.push_back(now);
        a[now]=-a[now];
    }
}
void dfs1(int now,int fa){
    for(int i=head[now];i;i=e[i].next){
        int to=e[i].v;
        if(to==fa)
            continue;
        dfs1(to,now);
    }
    if(a[now]==-1)
        son[fa]++;
    son[fa]+=son[now];
}
signed main() {
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=1;i<n;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    dfs1(1,0);
    a[1]=-a[1];
    dfs2(1,0);
    if(a[1]==-1){
        int to=e[head[1]].v;
        ans.push_back(to);
        ans.push_back(1);
        ans.push_back(to);
    }
    for(int i:ans)
        printf("%d ",i);
    printf("\n");
    return 0;
}
View Code