问题描述
给定无向连通图G=(V, E)和m种不同的颜色,用这些颜色为图G的各顶点着色,每个顶点着一种颜色。是否有一种着色法使G中相邻的两个顶点有不同的颜色。这个问题是图的m可着色判定问题。若一个图最少需要m种颜色才能使图中每条边连接的两个顶点着不同颜色,则称这个数m为该图的色数。求一个图的色数m的问题称为图的m可着色优化问题。
例如:点个数n=7,颜色m=3的涂色方案
算法设计
一般连通图的可着色问题,不仅限于可平面图。
给定图G=(V,E)和m种颜色,如果该图不是m可着色,给出否定回答;若m可着色,找出所有不同着色方法。
算法思路
设图G=(V, E), |V|=n, 颜色数= m, 用邻接矩阵a表示G, 用整数1, 2…m来表示
m种不同的颜色。顶点i所着的颜色用x[i]表示。
问题的解向量可以表示为n元组x={ x[1],…,x[n] }. x[i]∈{1,2,…,m},
解空间树为排序树,是一棵n+1层的完全m叉树.
在解空间树中做深度优先搜索, 约束条件:如果a[j][i]=1 , x[i] ≠ x[j]
m=3,n=3时的解空间树
再举个例子
对于下图,写出图着色算法得出一种着色方案的过程。
顶点数量n=4, 色数:m=3
m=4,n=3时的解空间树
X[1]←1 , 返回 true
X[2]←1, 返回false; X[2]←2, 返回 true
X[3]←1 ,返回false; X[3]←2, 返回false;X[3]←3, 返回 true
X[4]←1, 返回false; X[4]←2, 返回false;X[4]←3, 返回 true
着色方案:(1,2,3,3)
复杂度分析
图m可着色问题的解空间树中,内结点个数是:
对于每一个内结点,在最坏情况下,用ok检查当前扩展结点每一个儿子的颜色可用性需耗时O(mn)。
因此,回溯法总的时间耗费是
算法
#include <bits/stdc++.h>
using namespace std;
int m; //色数
int pointnum; //点数
int edgenum; //边数
int sum = 0; //符合条件的着色方案数量
int Graph[100][100]; //各点之间的关系 1:两点连接 0:两点断开
int x[100]; //存储各点的着色情况
void InPut()
{
int pos1, pos2; //起始点
cout<<"请输入点的个数和色数(p m):";
cin>>pointnum>>m;
cout<<"请输入边的个数: ";
cin>>edgenum;
memset(Graph, 0, sizeof(Graph));
cout<<"输入边的起始点信息(起点 终点):"<<endl;
for(int i = 1; i <= edgenum; ++i)
{
cin>>pos1>>pos2;
Graph[pos1][pos2] = Graph[pos2][pos1] = 1;
}
}
//判断当前点的着色是否合法合法, i 就是递归层数,也表明已经着色的节点索引
bool IsOk(int i)
{
for(int j = 1; j < i; ++j)
//两点如果相通并且与周围点的着色相同,就结束判断,表明当前的颜色选择不合法。
if(Graph[i][j] == 1 && x[j] == x[i])
return false;
return true;
}
//核心代码
void BackTrack(int i)
{
if(i > pointnum)
{
sum += 1;
cout<<"方法 "<<sum<<" :";
for(int j = 1; j <= pointnum; ++j)
{
cout<<x[j];
}
cout<<endl;
return;
}
else
{
for(int j = 1; j <= m; ++j)
{
x[i] = j;
if(IsOk(i))
BackTrack(i + 1);
x[i] = 0;
}
}
}
void OutPut()
{
cout<<"一共有 "<<sum<<" 种绘色方案"<<endl;
}
int main()
{
InPut();
BackTrack(1);
OutPut();
}
测试样例
输入:
请输入点的个数和色数(p m):5 4
请输入边的个数: 8
输入边的连接信息(点1 点2):
1 3
1 2
1 4
2 3
2 4
2 5
3 4
4 5
输出:
方法 1 : 1 2 3 4 1
方法 2 : 1 2 3 4 3
方法 3 : 1 2 4 3 1
方法 4 : 1 2 4 3 4
方法 5 : 1 3 2 4 1
方法 6 : 1 3 2 4 2
方法 7 : 1 3 4 2 1
方法 8 : 1 3 4 2 4
方法 9 : 1 4 2 3 1
方法 10 : 1 4 2 3 2
方法 11 : 1 4 3 2 1
方法 12 : 1 4 3 2 3
方法 13 : 2 1 3 4 2
方法 14 : 2 1 3 4 3
方法 15 : 2 1 4 3 2
方法 16 : 2 1 4 3 4
方法 17 : 2 3 1 4 1
方法 18 : 2 3 1 4 2
方法 19 : 2 3 4 1 2
方法 20 : 2 3 4 1 4
方法 21 : 2 4 1 3 1
方法 22 : 2 4 1 3 2
方法 23 : 2 4 3 1 2
方法 24 : 2 4 3 1 3
方法 25 : 3 1 2 4 2
方法 26 : 3 1 2 4 3
方法 27 : 3 1 4 2 3
方法 28 : 3 1 4 2 4
方法 29 : 3 2 1 4 1
方法 30 : 3 2 1 4 3
方法 31 : 3 2 4 1 3
方法 32 : 3 2 4 1 4
方法 33 : 3 4 1 2 1
方法 34 : 3 4 1 2 3
方法 35 : 3 4 2 1 2
方法 36 : 3 4 2 1 3
方法 37 : 4 1 2 3 2
方法 38 : 4 1 2 3 4
方法 39 : 4 1 3 2 3
方法 40 : 4 1 3 2 4
方法 41 : 4 2 1 3 1
方法 42 : 4 2 1 3 4
方法 43 : 4 2 3 1 3
方法 44 : 4 2 3 1 4
方法 45 : 4 3 1 2 1
方法 46 : 4 3 1 2 4
方法 47 : 4 3 2 1 2
方法 48 : 4 3 2 1 4
一共有 48 中绘色方案