2021牛客寒假算法基础集训营1 C题-红与蓝

题目:
在这里插入图片描述
比赛的时候看这道题,把它想复杂了,以为是其他图论的算法,赛后看别人写的才知道就是深搜一下就行。o(╥﹏╥)o

题解:
可以发现,树的叶子节点肯定是与它的父亲节点相匹配的,所以我们深搜一遍,从底层往上去模拟匹配的过程,对于以i为根节点的子树,我们先将它的子子树匹配好,如果 与 i 相邻的儿子节点都有匹配关系,那么说明 i 节点肯定要跟它的父亲节点匹配,如果只剩 1 个点未匹配,那么就让他和 i 节点匹配,如果存在多个,那么肯定不存在解。
最后我们再对根节点任意涂一种颜色,然后根据匹配关系对其他节点依次涂色。

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int>pii;
const int MAXN=1e5+5;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
struct node
{
    int to;
    int next;
}e[MAXN<<1];
int cnt=0;
int head[MAXN];
int match[MAXN];
int colar[MAXN];
void add(int u,int v)
{
    e[cnt].to=v;
    e[cnt].next=head[u];
    head[u]=cnt++;
}
void dfs(int u,int f)
{
    int num=0;
    for(int i=head[u];i!=-1;i=e[i].next){
        int v=e[i].to;
        if(v==f) continue;
        dfs(v,u);
        if(!match[v]){
            num++;
            if(num==1){
                match[u]=v;
                match[v]=u;
            } 
        }
    }
}
void solve(int u,int f,int co)
{
    colar[u]=co;
    for(int i=head[u];i!=-1;i=e[i].next){
        int v=e[i].to;
        if(v==f) continue;
        if(match[u]==v){
            solve(v,u,co);

        }else{
            solve(v,u,1-co);
        }
    }
}
int main()
{
    int n;
    cin>>n;
    memset(head,-1,sizeof head);
    for(int i=1;i<=n-1;i++){
        int u,v;
        cin>>u>>v;
        add(u,v);
        add(v,u);
    }
    dfs(1,-1);
    for(int i=1;i<=n;i++){
        if(!match[i]){
            printf("-1\n");
            return 0;
        }
    }
    solve(1,-1,1);
    for(int i=1;i<=n;i++){
        printf("%c",colar[i]?'R':'B');
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值