算法实践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
*/
posted @ 2021-06-23 02:24  stff577  阅读(173)  评论(0)    收藏  举报