题目描述
你拿到了一棵树,请你给每个顶点染成红色或蓝色。
要求:每个红点周围有且仅有一个红点,每个蓝点周围有且仅有一个蓝点。
“周围”的定义:某点周围的点指通过邻边直接连接的点。
所谓树,即没有自环、重边和回路的无向连通图。
输入描述:
第一行一个正整数 n,代表树的顶点个数。(1≤n≤100000)
接下来的n−1行,每行两个正整数u和v,代表点u和点v有一条边连接。 (1≤u,v≤n)
保证输入的一定是一棵合法的树。
输出描述:
如果可以达成染色的要求,请输出一个长度为n的字符串,第i个字符代表第i个顶点的染色情况,‘B’ 代表蓝色,‘R’ 代表红色。(若有多种合法染色的方法,输出任意一种即可)
否则直接输出-1。
输入
4
1 2
2 3
3 4
输出
RRBB
说明
1为红点,它连接的边有只有一个红点:2
2为红点,它连接的边有只有一个红点:1
3为蓝点,它连接的边有只有一个蓝点:4
4为蓝点,它连接的边有只有一个蓝点:3
思路
由于需要将树进行染色,所以我们可以采取DFS遍历树。根据题目要求,每个节点染完色后,其周围应当有且仅有一个节点与其同色。由此可知我们首先需要从叶子节点开始将树上的节点进行分类,在此过程中若出现了两个节点选取同一个父节点(无法满足周围有且仅有一个节点与其同色)或者配对后根节点无法成功配对,则不可能满足条件。而对于可以正确配对的树,我们只需要从根节点向下再次DFS遍历树,将经过的节点染上对应颜色即可。
代码
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
const int maxn=1e6+5;
typedef long long ll;
bool flag;
int n,cnt,tot,col[maxn],pre[maxn],head[maxn];
struct node
{
int to;
int next;
}maze[maxn];
void add(int u,int v)
{
maze[++cnt].next=head[u];
maze[cnt].to=v;
head[u]=cnt;
}
void dfs(int x,int fa)
{
int son=0;
for(int i=head[x];i;i=maze[i].next)
{
int to=maze[i].to;
if(to==fa)
continue;
son++;
dfs(to,x);
}
if(son==0||pre[x]==0)
{
if(pre[fa])
{
flag=1;
return ;
}
pre[x]=pre[fa]=++tot;
}
}
void dfs1(int x,int fa)
{
for(int i=head[x];i;i=maze[i].next)
{
int to=maze[i].to;
if(to==fa)
continue;
if(pre[x]==pre[to])
col[to]=col[x];
else
col[to]=col[x]^1;
dfs1(to,x);
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<n;i++)
{
int u,v;
cin>>u>>v;
add(u,v);
add(v,u);
}
col[1]=1;
dfs(1,0);
if(flag||pre[0])
{
cout<<"-1"<<"\n";
return 0;
}
dfs1(1,0);
for(int i=1;i<=n;i++)
{
if(col[i]==1)
cout<<"R";
else
cout<<"B";
}
return 0;
}
版权声明:本文为WTMDNM_原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。