2021牛ゲスト冬休みアルゴリズム基本トレーニングキャンプ1C-赤と青(二部着色)

トピックリンク:ここをクリック〜

トピック

  • 木ができました。各頂点を赤または青に染めてください。
  • 要件:各赤い点の周りに1つだけの赤い点があり、各青い点の周りに1つだけの青い点があります。
  • 最後に、各ポイントの色を出力します。R/ B、不可能な場合は-1を出力します。
  • 範囲1≤n≤100000

アイデア

  • 赤a1の側に赤a2が1つしかないため、赤a2の側に赤a1が1つだけあります。2つを1つのポイントにバインドできます。青いポイントは同じなので、ポイントの数は次のようになります。でも。
  • 次に、問題は2部グラフの色に変換され、2つの色しかなく、隣接する色が異なります。次に、各リーフノードには親が1つしかないため、リーフノードからバインドできます。親がバインドされている場合、そのようなグラフはありません。
  • ポイントに結合した後、それは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