首页 > 其他 > 详细

图的m着色问题

时间:2020-05-26 23:09:05      阅读:74      评论:0      收藏:0      [点我收藏+]

问题

给定无向连通图Gm种颜色,用这些颜色给图的顶点着色,每个顶点一种颜色。如果要求G的每条边的两个顶点着不同颜色。给出所有可能的着色方案;如果不存在,则回答“NO”。

 

解析

利用回溯法。涂的时候从颜色1开始到m,每当涂上一个色,要判断第c个点是否可以涂这个色,不可以的话就不再往下涂了,改试另一个颜色,可以的话就继续。当c>n的时候即前n个点都涂完了,然后输出结果并cout++计数。

 

设计

if(c>n){//如果涂的数目大于n,则表示已经成功涂完
    输出color数组;
    return;
}
for(int i=1;i<=m;i++){
    color[c]=i;
    if(点c可以涂){
        draw(c+1);
    }
    color[c]=0;//回溯
}

 

分析

n个点,最坏情况下,每个点需要检查每一个子节点,复杂度为O(mn),所以总的时间复杂度为O(nm^n)

 

源码

/*
author: keke
project name:图的m着色问题
Time Complexity: O(nm^n)
*/
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define db double
const int maxn = 1010;
int n, m, f, t, sum, color[maxn];
bool p[maxn][maxn];
bool jud(int x) {
    for (int i = 1; i <= n; i++) {
        if (p[x][i] && color[x] == color[i]) return false;
    }
    return true;
}
void draw(int x) {
    if (x > n) {//如果涂色数目大于n,则表示已经完成全部涂色
        for (int i = 1; i <= n; i++) cout << color[i] << (i == n ? "\n" : " ");
        ++sum;
        return;
    }
    for (int i = 1; i <= m; i++) {
        color[x] = i;
        if (jud(x)) draw(x + 1);
        color[x] = 0;//回溯
    }
}
int main() {
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(2);
    cin >> n >> m;
    while (cin >> f >> t) {  //不断读取图的边,建图
        if (f == 0 && t == 0) break;
        p[f][t] = p[t][f] = true;  //双向边
    }
    draw(1);
    cout << "总共有" << sum << "种涂色方案" << "\n";
    return 0;
    // good job!
}

 

图的m着色问题

原文:https://www.cnblogs.com/powerkeke/p/12968666.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!