CF780C_Andryusha and Colored Balloons_染色盘_染色问题_dfs类似问题

CF780C_Andryusha and Colored Balloons
题目概述
n个节点n-1条边的无向图,保证连通(就是一棵树),要给所有点染色,图中任意3个直接连通的点所用的颜色不能相同,n最多2*1e5个点,要求用最少的颜色种类来染色,输出所有点的颜色情况,任意一种即可。

解题思路

第一点——找到颜色种类K
其实最少用多少种颜色是好求的,因为一个点周围的颜色(也就是所连的点的颜色)都是不能相同,再加上这个点自己,所以我们可以先求出来哪个点所连的点数最多,再加上它自己就是最少的颜色种类,因为相当于最难满足的我们满足了,其他的点最好满足了。
第二点——染色
我们可以在遍历整个图的过程中就给点进行染色,这个时候我们可以采用一种染色盘的方法。
例如:
样例二的图
样例二的图
根据第一点我们可以求出最少的颜色种类是5,那么好,我们可以这5种颜色制作成一个颜色盘(就是循环数组0,1,2,3,4,输出的时候加一即可),就像是时钟那样。
x = 1,c = 0
我们从节点1开始,染色0,那么第一个与1相邻的颜色就是(c+1)%k,但是这样推下去不能和节点x的pre节点(父节点)的颜色相同,在代码中观察。

vector<int>col(n + 1);
col[0] = k;
vector<bool>vis(n + 1);
auto dfs = [&](auto&& dfs, int x, int c,int pre)->void {
	vis[x] = 1;
	col[x] = c;
	for (auto& y : g[x]) {
		if (vis[y]) continue;
		c = (c + 1) % k;
		while(c==col[pre]) c = (c + 1) % k;
		dfs(dfs, y, c,x);
	}
};
dfs(dfs, 1, 0, 0);

dfs的搜索图如下
dfs_search
点的先后顺序的问题,有些点的颜色可能有所不同,但都是满足上述点与点之间的性质的,1的pre记录的是0,是一个不存在的点,不需要再特判点了,写起来比较简洁。

code

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);

	int n, m;
	cin >> n;
	m = n - 1;
	int k = 0;
	vector<vector<int>>g(n + 1);
	while (m--) {
		int a, b;
		cin >> a >> b;
		g[a].push_back(b);
		g[b].push_back(a);
		//找最大的连接数
		k = max(k, (int)g[a].size());
		k = max(k, (int)g[b].size());
	}
	//加上哪个点它自己
	k++;
	//记录点的颜色
	vector<int>col(n + 1);
	col[0] = k;
	//记录点有没有被搜索过
	vector<bool>vis(n + 1);
	auto dfs = [&](auto&& dfs, int x, int c,int pre)->void {
		vis[x] = 1;
		col[x] = c;
		for (auto& y : g[x]) {
			if (vis[y]) continue;
			c = (c + 1) % k;
			while(c==col[pre]) c = (c + 1) % k;
			dfs(dfs, y, c,x);
		}
	};
	dfs(dfs, 1, 0, 0);
	cout << k << endl;
	for (int i = 1; i <= n; i++) cout << col[i] + 1 << " ";
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值