红和蓝

时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
Special Judge, 64bit IO Format: %lld
题目描述
你拿到了一棵树,请你给每个顶点染成红色或蓝色。
要求:每个红点周围有且仅有一个红点,每个蓝点周围有且仅有一个蓝点。
“周围”的定义:某点周围的点指通过邻边直接连接的点。
所谓树,即没有自环、重边和回路的无向连通图。
输入描述:
第一行一个正整数 n,代表树的顶点个数.。(1≤n≤100000)
接下来的n−1行,每行两个正整数u和v,代表点u和点v有一条边连接。
保证输入的一定是一棵合法的树。(1<u,v<100000)
输出描述:
如果可以达成染色的要求,请输出一个长度为n的字符串,第 i 个字符代表第 i个顶点的染色情况,‘B’ 代表蓝色,‘R’ 代表红色。(若有多种合法染色的方法,输出任意一种即可)
否则直接输出-1。

输入:
样例1
4
1 2
2 3
3 4

样例2
4
1 2
1 3
1 4

输出:

样例1
RRBB

样例2
-1

思路: 核心:构造
每个点只有一个同色点,从底下开始看,每个叶子结点必定和父亲同色,如果父亲已经染色了,无解。
如果是叶子结点,或者儿子都已染色,那么当前结点和父亲同色。
第一遍dfs,看是否可行,如果可行就赋予同编号
如果可行,第二遍dfs,染色

新年快乐 各位 >-<

//红和蓝
//构造
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;


int n,tot=0,cnt=0;
bool boo=1;      //是否有解
int f[100010];   //每个点的编号情况
int col[100010]; //每个点的染色情况
int head[100010];

struct ty
{
    
    
    int t,next;
}edge[200010];

void addedge(int x ,int y)
{
    
    
    edge[++tot].t=y;
    edge[tot].next=head[x];
    head[x]=tot;
}

void dfs1(int x, int fa)
{
    
    
    int son=0;
    for(int i=head[x]; i!=-1; i=edge[i].next)
    {
    
    
        if(edge[i].t==fa )    continue;
        son++;
        dfs1(edge[i].t, x);
    }

    if( son ==0 || f[x]==0 ) //没有儿子或者当前结点未染色,当前结点就和父亲同色
    {
    
    
        if( f[fa]!=0 ) {
    
    boo=0; return ;}//如果结点父亲已经染色了,无解
        f[x] = f[fa] =++cnt; //否则当前结点和父亲同色(编号相同)
    }
}

void dfs2(int x ,int fa)
{
    
    
    for(int i=head[x]; i!=-1 ;i=edge[i].next)
    {
    
    
        if( edge[i].t== fa) continue;
        if(f[edge[i].t]==f[x])   col[edge[i].t]=col[x];
        else col[edge[i].t]=col[x]^1;
        dfs2(edge[i].t,x);
    }
}
//void dfs2(int x. int fa)
int main()
{
    
    
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);

    memset(head, -1, sizeof(head));
    memset(edge, -1, sizeof(edge));
    cin>>n;
    for(int i=1; i<=n-1 ;i++) //存图
    {
    
    
        int x,y;
        cin>>x>>y;
        addedge(x,y);
        addedge(y,x);
    }
    dfs1(1,0); //先给每个点配搭档,第一步搜检查可行性

    if( boo==0 || f[0]!=0 ) //是否可行,还要看根节点是否“孤寡”
    {
    
    
        printf("-1\n");
        return 0;
    }

    col[1]=1; //先给根节点染色
    //第二搜,染色
    dfs2(1,0); //再搜一遍,看每个结点的编号情况,如果相同说明颜色相同,否则颜色相反

    for(int i=1; i<=n ;i++)
    {
    
    
        if(col[i]==1) printf("R");
        else printf("B");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_53688600/article/details/113824865