时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
Special Judge, 64bit IO Format: %lld
题目描述
你拿到了一棵树,请你给每个顶点染成红色或蓝色。
要求:每个红点周围有且仅有一个红点,每个蓝点周围有且仅有一个蓝点。
“周围”的定义:某点周围的点指通过邻边直接连接的点。
所谓树,即没有自环、重边和回路的无向连通图。
输入描述:
第一行一个正整数 n,代表树的顶点个数.。(1≤n≤100000)
接下来的n−1行,每行两个正整数u和v,代表点u和点v有一条边连接。
保证输入的一定是一棵合法的树。(1<u,v<100000)
输出描述:
如果可以达成染色的要求,请输出一个长度为n的字符串,第 i 个字符代表第 i个顶点的染色情况,‘B’ 代表蓝色,‘R’ 代表红色。(若有多种合法染色的方法,输出任意一种即可)
否则直接输出-1。
输入:
样例1
4
1 2
2 3
3 4
样例2
4
1 2
1 3
1 4
输出:
样例1
RRBB
样例2
-1
思路: 核心:构造
每个点只有一个同色点,从底下开始看,每个叶子结点必定和父亲同色,如果父亲已经染色了,无解。
如果是叶子结点,或者儿子都已染色,那么当前结点和父亲同色。
第一遍dfs,看是否可行,如果可行就赋予同编号
如果可行,第二遍dfs,染色
新年快乐 各位 >-<
//红和蓝
//构造
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,tot=0,cnt=0;
bool boo=1; //是否有解
int f[100010]; //每个点的编号情况
int col[100010]; //每个点的染色情况
int head[100010];
struct ty
{
int t,next;
}edge[200010];
void addedge(int x ,int y)
{
edge[++tot].t=y;
edge[tot].next=head[x];
head[x]=tot;
}
void dfs1(int x, int fa)
{
int son=0;
for(int i=head[x]; i!=-1; i=edge[i].next)
{
if(edge[i].t==fa ) continue;
son++;
dfs1(edge[i].t, x);
}
if( son ==0 || f[x]==0 ) //没有儿子或者当前结点未染色,当前结点就和父亲同色
{
if( f[fa]!=0 ) {boo=0; return ;}//如果结点父亲已经染色了,无解
f[x] = f[fa] =++cnt; //否则当前结点和父亲同色(编号相同)
}
}
void dfs2(int x ,int fa)
{
for(int i=head[x]; i!=-1 ;i=edge[i].next)
{
if( edge[i].t== fa) continue;
if(f[edge[i].t]==f[x]) col[edge[i].t]=col[x];
else col[edge[i].t]=col[x]^1;
dfs2(edge[i].t,x);
}
}
//void dfs2(int x. int fa)
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
memset(head, -1, sizeof(head));
memset(edge, -1, sizeof(edge));
cin>>n;
for(int i=1; i<=n-1 ;i++) //存图
{
int x,y;
cin>>x>>y;
addedge(x,y);
addedge(y,x);
}
dfs1(1,0); //先给每个点配搭档,第一步搜检查可行性
if( boo==0 || f[0]!=0 ) //是否可行,还要看根节点是否“孤寡”
{
printf("-1\n");
return 0;
}
col[1]=1; //先给根节点染色
//第二搜,染色
dfs2(1,0); //再搜一遍,看每个结点的编号情况,如果相同说明颜色相同,否则颜色相反
for(int i=1; i<=n ;i++)
{
if(col[i]==1) printf("R");
else printf("B");
}
return 0;
}