博主未授权任何人或组织机构转载博主任何原创文章,感谢各位对原创的支持! 博主链接
问题描述
描述: 你拿到了一棵树,请你给每个顶点染成红色或蓝色。 要求:每个红点周围有且仅有一个红点,每个蓝点周围有且仅有一个蓝点。 “周围”的定义:某点周围的点指通过邻边直接连接的点。 所谓树,即没有自环、重边和回路的无向连通图。
输入描述: 第一行一个正整数 n,代表树的顶点个数.。(1≤n≤100000) 接下来的 n-1 行,每行两个正整数 u 和 v,代表点 u 和点 v 有一条边连接。 (1≤u,v≤n) 保证输入的一定是一棵合法的树。
输出描述: 如果可以达成染色的要求,请输出一个长度为 n 的字符串,第 i 个字符代表第 i 个顶点的染色情况,‘B’ 代表蓝色,‘R’ 代表红色。(若有多种合法染色的方法,输出任意一种即可) 否则直接输出-1。
示例1: 输入:
4 1 2 2 3 3 4
输出:
RRBB 说明: 1为红点,它连接的边有只有一个红点:2 2为红点,它连接的边有只有一个红点:1 3为蓝点,它连接的边有只有一个蓝点:4 4为蓝点,它连接的边有只有一个蓝点:3
示例2: 输入:
4 1 2 1 3 1 4
输出: -1 说明: 可以证明,无论怎么染色,都无法满足题目的要求。
问题分析
- ①对于叶子节点,周围只有一个点就是它的父亲节点,题目要求每个点周围有且仅有一个红点/蓝点,所以叶子节点的颜色与其父亲节点的颜色一定是相同的;
- ②如果一个节点有多个叶子节点,那么整颗树是无法染色的,因为如果第一个叶子节点和父节点颜色都是R,根据题目要求第二个叶子节点应该是B,但是这样又不符合我们上面①分析的结果,所以如果一个节点有多个叶子节点,结果一定是 -1;
解题思路
C代码
#include <stdio.h>
#include <string.h>
int mark = 0;
int head[100010];
struct ty
{
int value;
int next;
}edge[200010];
int dp[100010]={0};
int color[100010]={0};
void addedge(int x, int y,int pos)
{
edge[pos].value = y;
edge[pos].next = head[x];
head[x] = pos;
}
int dfs1(int x,int father)
{
int son=0;
for(int i=head[x];i != -1;i = edge[i].next)
{
if(edge[i].value != father)
{
++son;
if(dfs1(edge[i].value,x)) return 1;
}
}
if(son == 0 || dp[x]==0)
{
if(dp[father] !=0) return 1;
dp[x] = dp[father] = ++mark;
}
return 0;
}
void dfs2(int x,int father)
{
for(int i=head[x];i != -1;i = edge[i].next)
{
if(edge[i].value != father)
{
if(dp[edge[i].value] == dp[x])
color[edge[i].value] = color[x];
else
color[edge[i].value] = !color[x];
dfs2(edge[i].value, x);
}
}
}
int main()
{
int x,y,n,pos=1;
scanf("%d",&n);
memset(head, -1, sizeof(head));
memset(edge, -1, sizeof(edge));
for(int i=1;i<n;++i)
{
scanf("%d%d",&x,&y);
addedge(x, y,pos);
++pos;
addedge(y, x,pos);
++pos;
}
if(dfs1(1,0) || dp[0])
{
printf("-1");
return 0;
}
color[1]=1;
dfs2(1,0);
for(int i=1;i<=n;++i)
{
printf("%c",color[i]?'R':'B');
}
return 0;
}
这里是从善若水的博客,感谢您的阅读💯💯💯
|