回溯法之图的m着色问题

回溯法之图的m着色问题


1. 问题描述

​ 给定无向连通图\(G\)\(m\)种不同的颜色。用这些颜色为图\(G\)的各个顶点着色,每个顶点着一种颜色。是否有一种着色发使\(G\)中每条边的2个顶点着不同颜色。这个问题是图的\(m\)可着色判定问题。若一个图最少需要\(m\)种颜色才能使图中每条边链接的2个顶点着不同颜色,则称这个数\(m\)为该图的色数。求一个图的色数\(m\)的问题称为图的\(m\)可着色优化问题。

2.问题分析

​ 本问题只探讨对于给定的\(m\),求解其可\(m\)着色的方案数
解向量:\((x_1, x_2, ..., x_n)\)表示顶点\(i\)所着颜色\(x_i\)
可行性约束函数:顶点\(i\)与已着色的相邻顶点颜色不重复

3.代码求解

​ 使用变量:

/**
 * n    国家数
 * m    可用颜色数
 * a    图的邻接矩阵
 * x    当前解
 * sum  着色方案数
 **/
int n = MAX;
int 0m;
int a[MAX + 1][MAX + 1] = {
    {0, 0, 0, 0, 0, 0},
    {0, 0, 1, 1, 1, 0},
    {0, 1, 0, 1, 1, 1},
    {0, 1, 1, 0, 1, 0},
    {0, 1, 1, 1, 0, 1},
    {0, 0, 1, 0, 1, 0}
};
int x[MAX + 1];
long sum = 0;

​ 核心代码:

// ok约束函数
// 要求a[k][j] == 1即俩顶点相邻
// x[j] == x[k]即二者的颜色重复
// 当二者都满足时,即该节点不符合剪枝函数,剪去
int ok(int k) {
    for (int j = 1; j < k; j++)
        if (a[k][j] && (x[j] == x[k]))
            return 0;
    return 1;
}

// t > n代表一种着色方案通过
// 通过遍历m,对各个结点设置不同的颜色
// 然后通过剪枝函数,只留下相邻顶点颜色不重复的分支,继续递归求解
void BackTrack(int t) {
    if (t > n)
        sum++;
    else
        for (int i = 1; i <= m; i++) {
            x[t] = i;
            if (ok(t))
                BackTrack(t + 1);
        }
}

4. 完整代码

/**
 * 回溯法之图的n着色问题
 **/
#include <stdio.h>
#include <stdlib.h>

#define MAX 5

/**
 * n    国家数
 * m    可用颜色数
 * a    图的邻接矩阵
 * x    当前解
 * sum  着色方案数
 **/
int n = MAX;
int m;
int a[MAX + 1][MAX + 1] = {
    {0, 0, 0, 0, 0, 0},
    {0, 0, 1, 1, 1, 0},
    {0, 1, 0, 1, 1, 1},
    {0, 1, 1, 0, 1, 0},
    {0, 1, 1, 1, 0, 1},
    {0, 0, 1, 0, 1, 0}
};
int x[MAX + 1];
long sum = 0;

// ok约束函数
// 要求a[k][j] == 1即俩顶点相邻
// x[j] == x[k]即二者的颜色重复
// 当二者都满足时,即该节点不符合剪枝函数,剪去
int ok(int k) {
    for (int j = 1; j < k; j++)
        if (a[k][j] && (x[j] == x[k]))
            return 0;
    return 1;
}

// t > n代表一种着色方案通过
// 通过遍历m,对各个结点设置不同的颜色
// 然后通过剪枝函数,只留下相邻顶点颜色不重复的分支,继续递归求解
void BackTrack(int t) {
    if (t > n)
        sum++;
    else
        for (int i = 1; i <= m; i++) {
            x[t] = i;
            if (ok(t))
                BackTrack(t + 1);
        }
}

void main() {
    m = 3;
    BackTrack(1);
    printf("%d\n", sum);

    system("pause");
}
posted @ 2020-12-12 20:51  Thoughtful_z  阅读(1389)  评论(0)    收藏  举报