トピックリンク:ここをクリック〜
トピック
- 木ができました。各頂点を赤または青に染めてください。
- 要件:各赤い点の周りに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;
}