一、算法要求
给定无向连通图G和m种不同的颜色。用这些颜色为图G的各顶点着色,每个顶点着一种颜色。是否有一种着色法,使G中每条边的2个顶点着有不同颜色?这个问题是图的m可着色判定问题。
若一个图最少需要m种颜色才能使图中每条边连接的2个顶点着不同颜色,则称这个数m为该图的色数。求一个图的色数m的问题称为图的m可着色优化问题。
如果一个图的所有顶点和边都能用某种方式画在平面上且没有任何两边相交,则称这个图是可平面图。著名的平面图的四色猜想是图的m可着色性判定问题的特殊情形。
1. 思路
如果我们把地图上的每一个区域退化成一个点,相邻的区域用连线连接起来,那么地图就变成了一个无向连通图,我们给地图着色就相当于给该无向连通图的每个点着色,要求有连线的点不能有相同颜色。这就是经典的图的m着色问题。给定无向连通图G和m种颜色,找出所有不同的着色方案,使相邻的区域有不同的颜色。
假设地图一共有7个区域,分别是A、B、C、D、E、F、G,我们现在按上面顺序进行编号1~7,每个区域用一个结点表示,相邻的区域有连线。那么地图就转化成了一个无向连通图。
二、完整代码
1. 主文件
main.cpp:
// Project4: 着色问题
#include <iostream>
#include <cstring>
#include <iomanip>
using namespace std;
const int numMax = 50,
n = 7,
m = 3,
edge = 12;
int sum = 0;//记录解的个数
int x[numMax],//解分量
map[numMax][numMax],//图的邻接矩阵
simple[12][2] = { {1,2},{1,3},{1,4},{2,3},{2,5},{3,4},
{3,5},{4,5},{4,7},{5,6},{5,7},{6,7} };
void CreatMap() {
int u, v;
memset(map, 0, sizeof(map));//邻接矩阵里面的数据初始化为0,
for (int i = 0; i < edge; i++){
u = simple[i][0];
v = simple[i][1];
map[u][v] = map[v][u] = 1;
}
int nn = 0;
for (int i = 0; i < edge; i++) {
for (int j = 0; j < edge; j++) {
if (map[i][j] != 0) {
cout << i << "-" << j << "|";
nn++;
if (nn % 6 == 0) {
cout << endl;
}
}
}
}
}
bool Coloring(int t) {
for (int j = 1; j < t; j++) {
if (map[t][j]) {
//如果t与j邻接
if (x[j] == x[t])//着色号是否相同
return false;
}
}
return true;
}
void Backtrack(int t) {
if (t > n) { //成功
sum++;
cout << "#No." << sum << ": ";
for (int i = 1; i <= n; i++)//输出该着色方案
cout << setw(3) << x[i];
cout << endl;
}
else {
for (int i = 1; i <= m; i++) {//每个结点尝试m种颜色
x[t] = i;
if (Coloring(t))
Backtrack(t + 1);
}
}
}
int main() {
cout << "#Number of nodes: " << setw(3) << n << endl;
cout << "#Number of colors:" << setw(3) << m << endl;
cout << "#The following is the adjacency of the undirected graph: " << endl;
CreatMap();
cout << "\n#Possible methods include:"<< endl;
Backtrack(1);
}
2. 效果展示
输入:
输出:
三、补充
算法复杂度分析:
(1)时间复杂度
最坏情况下,除了最后一层外,有1+m+m2+…+mn-1=(mn-1)(m-1)~mn-1个结点需要扩展,而这些结点每个都要扩展m个分支,总的分支个数为mn,每个分支都判断约束函数,判断约束条件需要O(n)的时间,因此耗时O(nmn)。在叶子结点处输出可行解需要耗时O(n),在最坏情况下回搜索到每一个叶子结点,叶子个数为mn,故耗时为O(nmn)。因此,时间复杂度为O(nmn)。
(2)空间复杂度
回溯法的另一个重要特性就是在搜索执行的同时产生解空间。在所搜过程中的任何时刻,仅保留从开始结点到当前扩展结点的路径,从开始结点起最长的路径为n。程序中我们使用x[]数组记录该最长路径作为可行解,所以该算法的空间复杂度为O(n)。
文档供本人学习笔记使用,仅供参考。