2021牛客寒假算法基础集训营1 C.红和蓝

题目链接

题目描述

你拿到了一棵树,请你给每个顶点染成红色或蓝色。
要求:每个红点周围有且仅有一个红点,每个蓝点周围有且仅有一个蓝点。
“周围”的定义:某点周围的点指通过邻边直接连接的点。
所谓树,即没有自环、重边和回路的无向连通图。

输入描述:

第一行一个正整数 n,代表树的顶点个数。(1≤n≤100000)
接下来的n−1行,每行两个正整数u和v,代表点u和点v有一条边连接。 (1≤u,v≤n)
保证输入的一定是一棵合法的树。

输出描述:

如果可以达成染色的要求,请输出一个长度为n的字符串,第i个字符代表第i个顶点的染色情况,‘B’ 代表蓝色,‘R’ 代表红色。(若有多种合法染色的方法,输出任意一种即可)
否则直接输出-1。

输入

4
1 2
2 3
3 4

输出

RRBB

说明

1为红点,它连接的边有只有一个红点:2
2为红点,它连接的边有只有一个红点:1
3为蓝点,它连接的边有只有一个蓝点:4
4为蓝点,它连接的边有只有一个蓝点:3

思路

由于需要将树进行染色,所以我们可以采取DFS遍历树。根据题目要求,每个节点染完色后,其周围应当有且仅有一个节点与其同色。由此可知我们首先需要从叶子节点开始将树上的节点进行分类,在此过程中若出现了两个节点选取同一个父节点(无法满足周围有且仅有一个节点与其同色)或者配对后根节点无法成功配对,则不可能满足条件。而对于可以正确配对的树,我们只需要从根节点向下再次DFS遍历树,将经过的节点染上对应颜色即可。

代码

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
const int maxn=1e6+5;
typedef long long ll;
bool flag;
int n,cnt,tot,col[maxn],pre[maxn],head[maxn];
struct node
{
    int to;
    int next;
}maze[maxn];
void add(int u,int v)
{
    maze[++cnt].next=head[u];
    maze[cnt].to=v;
    head[u]=cnt;
}
void dfs(int x,int fa)
{
    int son=0;
    for(int i=head[x];i;i=maze[i].next)
    {
        int to=maze[i].to;
        if(to==fa)
            continue;
        son++;
        dfs(to,x);
    }
    if(son==0||pre[x]==0)
    {
        if(pre[fa])
        {
            flag=1;
            return ;
        }
        pre[x]=pre[fa]=++tot;
    }
}
void dfs1(int x,int fa)
{
    for(int i=head[x];i;i=maze[i].next)
    {
        int to=maze[i].to;
        if(to==fa)
            continue;
        if(pre[x]==pre[to])
            col[to]=col[x];
        else
            col[to]=col[x]^1;
        dfs1(to,x);
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n;
    for(int i=1;i<n;i++)
    {
        int u,v;
        cin>>u>>v;
        add(u,v);
        add(v,u);
    }
    col[1]=1;
    dfs(1,0);
    if(flag||pre[0])
    {
        cout<<"-1"<<"\n";
        return 0;
    }
    dfs1(1,0);
    for(int i=1;i<=n;i++)
    {
        if(col[i]==1)
            cout<<"R";
        else
            cout<<"B";
    }
    return 0;
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值