CF - 780 --C. Andryusha and Colored Balloons【BFS + 思维】

在这里插入图片描述

题意
给定一个1 到 n 的正方形,有n - 1个关系,每个关系是两个正方形相邻,
问从1号正方形开始染色,每个正方形周围的颜色和本身不相同,问最多需要多少种颜色
思路
PS:先开始想着bfs搜索,然后暴力枚举前面没用过的颜色,先用小的,结果T了,很现实。
转换思路, 分析枚举当前的结点时,这个结点的颜色收到父亲结点,和祖父结点的影响。例如此图

在这里插入图片描述

	当枚举3号结点时它就受到它父亲结点(1号结点)的影响,由于3号结点没有祖父结点,所以不管。
	再枚举到2号结点时,他就不能和(1, 3结点)的颜色相同。再到5号结点时,他不能和(1,3,2)的颜色相同。
	现在问题来了,怎么我们记录不和1,3相等容易,就是父亲结点和祖父结点不能相等,那么这个2怎么处理?
	就要用一个变量num初始为1,开始一直变大,当与父亲结点相连的儿子结点时,让num一直增大,
	取第一个不与父亲和祖父结点相同的颜色,这样保证这些兄弟之间的颜色不同,也保证了与父亲和祖父的颜色不同。
AC代码
/**
	思路:本题染色只和父亲结点,以及祖父结点有关系。
	每次遍历记录他的父亲结点和当前的颜色即可。 
**/
#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 2e5 + 5;
vector<int> g[maxn];
int val[maxn];
int fa[maxn];
queue<int> q;
void init(int n){
	for (int i = 1; i <= n; ++i){
		g[i].clear();
		val[i] = 0;
		fa[i] = i; 
	}
}
void bfs(int n){
	while (!q.empty()) 	q.pop();
	q.push(1);
	val[1] = 1;
	fa[1] = 1;
	int mx = 0;
	while (!q.empty()){
		int now = q.front(); q.pop();
		mx = max(mx, val[now]);
		int num = 1, len = g[now].size();
		for (int i = 0; i < len; ++i){
			int v = g[now][i];
			if (val[v])	continue;
			while (val[now] == num || val[fa[now]] == num)	num++;
			val[v] = num++;
			//now是v的父亲 
			fa[v] = now;
			q.push(v);
		}
	}
	printf("%d\n", mx);
	for (int i = 1; i <= n; ++i){
		if (i < n)	printf("%d ", val[i]);
		else	printf("%d\n", val[i]);
	}
}
void solve(){
	int n, u, v;
	scanf("%d", &n);
	init(n);
	for (int i = 0; i < n - 1; ++i){
		scanf("%d%d", &u, &v);
		g[u].push_back(v);
		g[v].push_back(u);
	}
	bfs(n);
}
int main(){
	solve();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星空皓月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值