2021牛客寒假算法基础集训营1 C-红和蓝(二分图染色)

题目链接:点这里~

题目大意

  • 你拿到了一棵树,请你给每个顶点染成红色或蓝色。
  • 要求:每个红点周围有且仅有一个红点,每个蓝点周围有且仅有一个蓝点。
  • 最后输出每个点的颜色,R/B,如果不可以输出-1
  • 范围1≤n≤100000

思路

  • 红a1边上只有一个红a2,那么红a2边上也只有一个红a1,两者可以绑定到成一个点,蓝点同理,所以点数一定是偶数。
  • 那么问题就转换成二分图染色,只有两种颜色,相邻的颜色不同。那么可以从叶节点往上绑定,因为每个叶节点只有一个父亲,如果这个父亲已经绑定过了,那么就不存在这样的图了。
  • 绑定成一个点之后呢,就可以dfs染色了。

ac代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 1e5 + 5;
int vis[maxn], id[maxn], pre[maxn], col[maxn];
//vis表示节点是否绑定过,id表示节点绑定的编号,pre表示父节点编号,col表示节点颜色
int flag = 0;
vector<int> v[maxn];
void dfs1(int s, int fa){
    for(auto it : v[s]){
        if(it == fa) continue;
        pre[it] = s;
        dfs1(it, s);
        if(flag) return;
    }
    //自下而上绑定
    if(!vis[s]){
        if(vis[pre[s]]){ //如果父亲已经绑定过了,那么节点s就成孤儿了,所以不行
            flag = 1;
            return;
        }
        vis[s] = vis[pre[s]] = 1;
        id[s] = id[pre[s]] = s; //绑定成节点s
    }
}
void dfs2(int s, int fa, int color){
    col[s] = color; //染色
    for(auto it : v[s]){
        if(it == fa) continue;
        if(id[s] == id[it]) dfs2(it, s, color); //绑定同一节点,颜色一样
        else dfs2(it, s, 1 ^ color); //否则是二分图上相邻节点,颜色不同
    }
}
int main(){
    int n; cin >> n;
    for(int i = 1; i < n; i ++){
        int x, y;
        cin >> x >> y;
        v[x].push_back(y);
        v[y].push_back(x);
    }
    if(n & 1){ //奇数不行
        puts("-1");
        return 0;
    }
    dfs1(1, 0); //绑定节点
    if(flag == 1){ //绑定失败
        puts("-1");
        return 0;
    }
    dfs2(1, 0, 1);//染色
    for(int i = 1; i <= n; i ++){
        if(col[i]) printf("R");
        else printf("B");
    }
    cout << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43911947/article/details/113552593