算法实践12 图的m着色问题
问题:
图的\(m\)着色问题。给定无向连通图\(G\)和\(m\)种颜色,用这些颜色给图的顶点着色,每个顶点一种颜色。如果要求\(G\)的每条边的两个顶点着不同颜色。给出所有可能的着色方案;如果不存在,则回答“NO”。
解析
为了找到所有方案,给每个点都要尝试\(m\)次。要满足边的两点不同色,染色后要检查周围点的染色情况,判断是否进行下一步递归。
设计
bool check(int u) {
for (auto v : G[u]) {
if (cor[v] == cor[u]) return false;
}
return true;
}
void dfs(int u) {
if (u > n) {
printf("case%d:", ++tot);
for (int i = 1; i <= n; ++i) {
printf(" %d", cor[i]);
}
puts("");
return;
}
for (int i = 1; i <= m; ++i) {
cor[u] = i;
if (check(u)) {
dfs(u + 1);
}
cor[u] = 0;
}
}
分析
每个点都要尝试\(m\)种颜色,复杂度 \(O(n^m)\),每次递归到最后需要检查\(tk\)条边,\(t\)为常数,复杂度为\(O(k)\),每次输出需要\(O(n)\),总时间复杂度\(O(kn^{m+1})\)
源码
https://github.com/Sstee1XD/Algorithm_homework/tree/main/实验12 图的m着色问题
#include <bits/stdc++.h>
using namespace std;
#define endl "\n"
const int inf = 0x3f3f3f3f;
const int N = 1e3 + 7;
int n, m, k, tot;
int cor[N];
vector<int> G[N];
bool check(int u) {
for (auto v : G[u]) {
if (cor[v] == cor[u]) return false;
}
return true;
}
void dfs(int u) {
if (u > n) {
printf("case%d:", ++tot);
for (int i = 1; i <= n; ++i) {
printf(" %d", cor[i]);
}
puts("");
return;
}
for (int i = 1; i <= m; ++i) {
cor[u] = i;
if (check(u)) {
dfs(u + 1);
}
cor[u] = 0;
}
}
void solve() {
tot = 0;
scanf("%d %d %d", &n, &m, &k); // 输入点数、颜色数、边数
for (int i = 1; i <= n; ++i) G[i].clear(), cor[i] = 0;
for (int i = 1, u, v; i <= k; ++i) {
scanf("%d %d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs(1);
if (!tot) puts("NO");
}
int main() {
// scanf("%d", &t);
int t = 1;
while (t--) solve();
return 0;
}
/*
5 3 5
1 2
2 3
3 4
3 5
1 5
*/

浙公网安备 33010602011771号