程序基本算法习题解析 回溯法求解图的m可着色判定问题

题目:

给定无向连通图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;
}

运行结果如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值