2021牛客寒假算法基础集训营1 C 红和蓝 二分图判定+构造

https://ac.nowcoder.com/acm/contest/9981/C

目录

题意

有一棵树,每个节点上都有一种颜色,要求每个红色点边上只有一个红色点,每个蓝色点边上只有一个蓝色点,问能否构造,否则输出-1。

分析

稍微画一下图可以注意到红色和蓝色都是成对出现的,也就是说用相邻的两个点对覆盖整棵树,而且不能重叠。看到点对问题可以想到二分图的染色问题,而这时我们要多处理一步,就是找出点对。

在这里插入图片描述
在此之前我们通过二分图判定,如果黑色点和白色点个数不相同,那么无法构成n/2个点对。排除掉不合法的形状,剩下的就是可以构造的形状了,所以放心去搞就行了。

我们发现每个子节点都只有一个父节点,因此我们可以把所有的点对找出来,每一个点对都先赋值为儿子的节点号。这里有一个问题,怎么去找点对,我们在第一次dfs的时候记录每个点的父亲节点,然后回溯的时候找点就可以了。

找到点对后就可以将两个点当成一个点,然后普通的二分图染色去搞就行了。

用了两次二分图的染色,三次dfs感觉有些麻烦了,不过思路还是比较清楚地。

Code

#include <bits/stdc++.h>
using namespace std;
//#define ACM_LOCAL
const int N = 2e5 + 10;
const int M = 5e5 + 10;
const int INF = 0x3f3f3f3f;
const double eps = 1e-4;
const int MOD = 1e9+7;
typedef long long ll;
typedef pair<int, int> PII;
vector<int> g[N];
int in[N], col[N], cnt, vis[N], fat[N], id[N];

void dfs1(int x, int fa, int color) {
    
    
    col[x] = color;
    if (color == 1) cnt++;
    for (auto v : g[x]) {
    
    
        if (v == fa) continue;
        fat[v] = x;
        dfs1(v, x, color ^ 1);
    }
}

void dfs2(int x, int fa, int rt) {
    
    
    for (auto v : g[x]) {
    
    
        if (v == fa) continue;
        dfs2(v, x, rt);
    }

    if (!vis[x]) {
    
    
        vis[x] = vis[fat[x]] = 1;
        col[x] = col[fat[x]] = x;
    }
}

void dfs3(int x, int fa, int color) {
    
    
    id[x] = color;
    for (auto v : g[x]) {
    
    
        if (v == fa) continue;
        if (col[v] == col[x]) {
    
    
            dfs3(v, x, color);
        } else {
    
    
            dfs3(v, x, color^1);
        }
    }
}

void solve() {
    
    
    int n; cin >> n;
    for (int i = 1; i <= n - 1; i++) {
    
    
        int u, v;
        cin >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    if (n % 2 != 0) {
    
    
        cout << -1 << endl;
        return;
    }
    memset(col, -1, sizeof col);
    dfs1(1, 0, 0);
    if (n / 2 != cnt) {
    
    
        cout << -1 << endl;
        return;
    }
    dfs2(1, 0, 1);
    dfs3(1, 0, 0);
    for (int i = 1; i <= n; i++) {
    
    
        if (id[i] == 0) cout << 'R';
        else cout << 'B';
    }
}
signed main() {
    
    
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
#ifdef ACM_LOCAL
    freopen("input", "r", stdin);
    freopen("output", "w", stdout);
#endif
    solve();
}
/*
 10
1 2
1 4
1 6
3 2
4 5
6 7
7 8
6 9
9 10
 */

猜你喜欢

转载自blog.csdn.net/kaka03200/article/details/113528118