题目:
给定无向连通图G和m种不同的颜色。用这些颜色为图G的各顶点着色,每个顶点着一种颜色。是否有一种着色法使G中每条边的两个顶点着不同颜色。
思路:
首先,需要输入的数据为:顶点数N,颜色数M,邻接矩阵adjMatrix(二维,表示顶点之间的关系,两点间有边相连为1,无边相连为0)。然后依次对各顶点进行着色,对每个顶点的着色规则是:从标号较小的颜色数开始尝试,每选定一种颜色,判断该顶点是否可以着此颜色(如果与该顶点有边相连的其它顶点未着此颜色,则该顶点可着此色)。直到所有顶点都着色完成,即可输出各顶点的颜色。
另外,介绍一下回溯法的概念:
回溯法又称试探法,采用“走不通就掉头”的思想,从一条路往前走,能进则进,不能进则退回来,换一条路再试。
回溯法的搜索策略如下:按照深度优先策略,采用先根遍历法构造解空间树,当搜索至解空间树的任意一点时,判断该节点是否包含问题的解,如果不包含,通过“剪枝过程”跳过以该节点为根的子树,逐层向其祖先节点回溯;否则,进入该子树,按深度优先策略搜索。
回溯法就是使用剪枝函数减去一些不可能达到最终状态的节点,从而减少状态空间树节点的生成。
例如如下的一个图:
其邻接矩阵为:
构造M叉树(点旁边的数字为颜色数):
红色枝中,顶点2与顶点3颜色相同,且有边相连,则该枝应该被煎掉,其它枝如是判断。
代码如下:
// Chapter10_1.cpp : Defines the entry point for the application.
// 图的m可着色判定问题:给定无向连通图G和m种不同的颜色。用这些颜色为图G的各顶点着色,
// 每个顶点着一种颜色。是否有一种着色法使G中每条边的两个顶点着不同颜色。
#include "stdafx.h"
#include<iostream>
using namespace std;
//定义全局变量
int N,M; //N:顶点数,M:可用颜色数
//顶点矩阵(颜色)
int *PointsColor = new int[N+1];
//图的邻接矩阵(二维数组)动态分配
int **adjMatrix = new int *[N+1];
int times = 1;
//判断图中第No个顶点的着色方案是否可行
int funCheck(int No)
{
//判断该顶点与其着同一色的其它顶点之间是否是有边连接
for(int i=1;i<=N;i++)
{
if(((adjMatrix[No][i]==1) && PointsColor[No]==PointsColor[i]))
{
return 0;
}
}
return 1;
}
//回溯法求解图的m可着色判断问题,t:第t个顶点
void drawColor(int t)
{
//如果所有顶点着色完成,输出着色方案
if(t>N)
{
cout << "***着色方案为***:" << endl;
cout << "<";
for(int i=1;i<=N;i++)
cout << PointsColor[i] << ' ';
cout << ">" << endl;
system("pause");
}
else
{
cout << "【第" << times++ << "次着色】" << endl;
//从编号较小的颜色开始尝试,检验该顶点是否可以着此颜色
for(int j=1;j<=M;j++)
{
PointsColor[t] = j; //先着一种颜色
if(funCheck(t)) //如果能着这个颜色
{
cout << "点" << t << "着" << j << "色" << endl;
drawColor(t+1); //着下一个顶点
}
//如果不能着该颜色,则先不着色(赋为0),换一种颜色重新着(继续for循环)
cout << "点" << t << "不能着" << j << "色" << endl;
PointsColor[t] = 0;
}
}
}
int main()
{
int i,j;
cout << "输入顶点数: ";
cin >> N;
cout << "输入可用颜色数: ";
cin >> M;
for(i=1;i<N+1;i++)
{
adjMatrix[i] = new int[N];
}
//输入邻接矩阵
cout << "输入顶点关系(两点间有边相连为1,无边相连为0): " << endl;
for(i=1;i<N+1;i++)
{
cout << "顶点" << i << "与其它点的连接关系(按顺序,与自身的关系为0): " << endl;
for(j=1;j<N+1;j++)
{
cin >> adjMatrix[i][j];
}
}
//初始化顶点颜色(0:不着色)
for(i=1;i<M+1;i++)
PointsColor[i] = 0;
//着色,从第一个顶点起
drawColor(1);
//释放空间
for(i=0;i<N+1;i++)
{
delete adjMatrix[i];
adjMatrix[i] = NULL;
}
delete [N+1]adjMatrix;
system("pause");
return 0;
}
运行结果如下: