Codeforces 763A

乍看之下感觉有点无从下手,,其实是个很简单的水题,陷入僵局

题目大意:给一棵树,树上每个节点都染色,问能否取下一个节点,使得剩余所有子树上的点的颜色都相同。能输出YES和取下的节点编号,否则输出NO。

解题思路:感觉无从下手,结果xjb找找情况画画图脑补个策略就行了——

  随便从一个点开始进行搜索,如果和它颜色不同的相邻节点个数(除去父节点)大于等于2,那答案肯定是它没跑了,如果在这之前已经确定下了一个答案并且这个答案不是自己,咖喱给给。

  如果和它颜色不同的相邻节点个数(除去父节点)为1,那么令答案为该相邻节点。同样如果已经确定答案但是答案不是自己,gg。

  随便测了几组数据没问题就交了过了。

  如果全部节点都是一个颜色,则出现flag为1而res尚未被赋值,特判输出之。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
#define sqr(x) ((x)*(x))
const int N=2e5+10;
int head[N],to[N<<1],nxt[N<<1],cnt;
int n,c[N],res,flag;
void init(){
    memset(head,-1,sizeof(head));
    cnt=res=0;
    flag=1;
}
void addEdge(int u,int v){
    nxt[cnt]=head[u];
    to[cnt]=v;
    head[u]=cnt++;
}
void dfs(int u,int pre){
    if(!flag) return;
    int tot=0,id;
    for(int i=head[u];~i;i=nxt[i]){
        int v=to[i];
        if(v==pre) continue;
        if(c[u]!=c[v]){
            tot++;
            id=v;
        }
    }
    if(tot>0){
        if(tot==1){
            if(res){
                if(res!=u) flag=0;
            }
            else res=id;
        }
        else{
            if(res&&res!=u) flag=0;
            else res=u;
        }
    }
    for(int i=head[u];~i;i=nxt[i]){
        int v=to[i];
        if(v==pre) continue;
        dfs(v,u);
    }
}
int main(){
    //freopen("in.txt","r",stdin);
    while(~scanf("%d",&n)){
        init();
        for(int i=1;i<n;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            addEdge(u,v),addEdge(v,u);
        }
        for(int i=1;i<=n;i++)
            scanf("%d",c+i);
        dfs(1,0);
        if(flag) printf("YES\n%d\n",res?res:1);
        else puts("NO");
    }
    return 0;
}

 

posted @ 2017-03-16 21:39  轶辰  阅读(253)  评论(0编辑  收藏  举报