一、题意
给出一个n个点m条边的连通图,每个点的度数不超过k(k为一个奇数),要求给每个点进行1...k的染色,使得相邻点颜色不同。
二、解析
首先按照题目的意思求出k,并且题目已经告诉我们k染色一定有解,因此接下来就是放心的dfs染色即可。
需要维护一个col[maxn]数组,0表示没有染色。这个col数组除了存放每个点的颜色,还充当了vis的角色。dfs的出口就是检查是否和周围已经染色的点重色了,没有则进行递归染色即可。
三、代码
#include <iostream>
#include <vector>
using namespace std;
const int maxn = 10000 + 5;
int n, m, k, col[maxn];
vector<int> G[maxn];
bool dfs(int u, int c) {
col[u] = c;
for(int v : G[u]) if(col[v] == c) {
col[u] = 0;
return 0;
}
// 由于可以保证一定有解,所以后面直接找解即可;否则还应该进行return 0的判断。
for(int v : G[u]) if(!col[v]) {
for(int i = 1; i <= k; i ++) if(dfs(v, i)) break;
}
return 1;
}
int main() {
bool first = 1;
while(cin >> n >> m) {
k = 0;
fill(col, col + n + 1, 0);
for(int i = 1; i <= n; i ++) G[i].clear();
while(m --) {
int u, v;
cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
for(int i = 1; i <= n; i ++) k = max(k, (int)G[i].size());
if(k % 2 == 0) k ++;
dfs(1, 1);
if(first) first = 0;
else cout << endl;
cout << k << endl;
for(int i = 1; i <= n; i ++) cout << col[i] << endl;
}
}四、归纳
染色问题 通过dfs解决,模板大致为:
bool dfs(int u, int c) { col[u] = c; // 根据 [已染色的结点] 进行重色判断, 重色则失败 for(int v : G[u]) if(col[v] == c) { col[u] = 0; return 0; } // 尝试对 [没染色的结点] 进行染色,同时也要进行是否成功的判断 bool res = 1; for(int v : G[u]) if(!col[v]) { bool ok = 0; for(int i = 1; !ok && i <= k; i ++) if(dfs(v, i)) ok = 1; if(!ok) { // 若某个点所有染色都染不了,则该次染色失败 res = 0; break; } } return res; }

京公网安备 11010502036488号