2021牛客寒假集训营第一场 C 红和蓝
红和蓝
https://ac.nowcoder.com/acm/contest/9981/C
题意
给一棵树,把他染成红蓝两种颜色。
要求:每个点周围有且仅有有一个点和自己颜色相同
不存在输出-1
分析
首先如果n是奇数肯定不存在,接着考虑其他情况,先说jie'l。
如果存在某一个点,他的 子树的节点数为奇数,这样的子树个数大于1个的话,则无解。
先从叶子节点考虑,因为叶节点只与父节点相连,所以父节点的颜色一定和自己相同。
如果有多个叶子的话,父节点与这些叶节点颜色相同,则无解。
可以推广到,如果子树节点个数为奇数,则必然会多出一个点只能和根组合,若这样的子树个数大于1,无解。
这里证明的并不严谨,只是帮助想象,有兴趣可以自己画一画推一推。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
#define x first
#define y second
const int N = 200010;
int n;
int e[N], ne[N], h[N], idx;
int cnt[N], sz[N]; // 子树的点数奇数的数量,以i为根的点数
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
bool dfs(int u, int fa)
{
sz[u] = 1;
for(int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if(j == fa) continue;
if(!dfs(j, u)) return false;
sz[u] += sz[j];
if(sz[j] & 1) cnt[u] ++;
}
if(cnt[u] > 1) return false;
return true;
}
int ans[N];
void dfs2(int u, int fa, int c)
{
ans[u] = c;
for(int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if(j == fa) continue;
if(sz[j] & 1) dfs2(j, u, c);
else dfs2(j, u, !c);
}
}
void solve()
{
memset(h, -1, sizeof h);
cin >> n;
for(int i = 0; i < n - 1; i ++)
{
int a, b;
cin >> a >> b;
add(a, b), add(b, a);
}
if(n & 1)
{
cout << -1 << endl;
return;
}
if(!dfs(1, -1))
{
cout << -1 << endl;
return;
}
dfs2(1, -1, 0);
for(int i = 1; i <= n; i ++)
if(ans[i]) cout << 'B';
else cout << 'R';
cout << endl;
}
int main()
{
/*ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t;
cin >> t;
while(t --)*/
solve();
}
查看9道真题和解析