题解 | #红和蓝#
红和蓝
https://www.nowcoder.com/practice/34bf2aaeb61f47be980b9ec0ab238c36
#include <iostream>
#include <cstring>
using namespace std;
const int N = 1e5 + 10;
int n;
int e[N * 2], ne[N * 2], h[N], idx;
// sons[i] 记录节点i为根的子树的节点数
int sons[N];
// 记录节点的颜色
int colors[N];
bool isFailed = false; // 是否染色失败
void add(int a, int b) {
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
//递归的 求以cur为根的树 有多少个节点
int calcSon(int cur, int last){
int sum = 1;
for(int i = h[cur]; i != -1; i = ne[i]){
// cur的孩子节点
int ch = e[i];
if(ch == last){ //防止向上递归(cur的孩子节点不能是它的父节点,虽然在遍历的时候cur和它父节点也存在边)
continue;
}
sum += calcSon(ch, cur);
}
sons[cur] = sum;
return sum;
}
void dfs(int t, int pt, int c){
/*
考虑每个节点i,
1. 当i和par_i(i的父节点)颜色相同时,i 的所有儿子子树(以i的子节点c_i为根的子树)节点数为偶数,且所有子树根结点
(i所有子节点)的颜色与节点i相反
2. 当i和par_i(i的父节点)颜色 不相同 时,i 的所有儿子子树(以i的子节点c_i为根的子树)中必须有且仅有一个子树的节点数为奇数,
其它子树的节点数都是偶数;且奇数节点数的子树根结点(i的某个子节点)的颜色与节点i相同,其它偶数节点数的子树根结点(i的除了奇数子树后所有的偶数子树的根节点) 的颜色与节点i 不相同
*/
if(isFailed)
return ;
colors[t] = c;
int cnt = 0;
for(int i = h[t]; i != -1; i=ne[i]){
int ci = e[i];
if(ci != pt){
cnt += (sons[ci] & 1); // 判断节点i的所有子树 root-ci 中是否有且仅有一个奇数子树(子树节点个数奇数个)
}
}
//经过上面的循环,cnt=1表示节点t的 子树中 有且仅有一个奇数子树; cnt=0表示节点t的 子树中 全部为偶数子树
if(colors[t] == colors[pt]){ //情况1,颜色相同
if(cnt==1){ // 节点i的所有子树 root-ci 中 【有且仅有一个奇数子树】
isFailed = true;
return ;
}
for(int i = h[t]; i != -1; i=ne[i]){
int child_i = e[i];
if(child_i != pt){ //保证不向 上(父节点)递归,虽然他们之间也存在边
dfs(child_i, t, c^1); // t作为父节点, 它的所有儿子子树 节点数为偶数,且所有子树 根结点 的颜色与节点i相反(异或1)
}
}
}else{ //情况2,颜色 相反
if(cnt!=1){ // 节点i的所有子树 root-ci 中 【不是 有且仅有一个奇数子树】
isFailed = true;
return ;
}
for(int i = h[t]; i != -1; i=ne[i]){
int child_i = e[i];
if(child_i != pt){
if(sons[child_i] & 1){ // 是一个奇数子树时,t的孩子节点child_i 颜色和t相同
dfs(child_i, t, c);
}else{
dfs(child_i, t, c^1);
}
}
}
}
}
int main() {
memset(h, -1, sizeof(h));
cin >> n;
int a, b;
for (int i = 1; i < n; i++) {
cin >> a >> b;
add(a, b), add(b, a);
}
//以节点1作为整棵树的根节点。计算节点1的节点数
sons[1] = calcSon(1,0);
dfs(1,0,1);
if(isFailed)
printf("-1\n");
else{
for(int i = 1; i <=n;i++){
if(colors[i])
printf("B");
else
printf("R");
}
}
return 0;
}
// 64 位输出请用 printf("%lld")


查看14道真题和解析