14回溯法——图的m着色问题

基于回溯法的图m着色问题

目录

  • 基于回溯法的图m着色问题
    • 1.问题
    • 2.解析
      • 举个栗子
    • 3.设计
    • 4.分析
    • 5.源码

回溯法的核心是:

用深度优先策略遍历整棵树,如果发现向下搜索不可能达到解节点,就回头。解向量在搜索过程中不断生成。

1.问题

给定无向连通图 G= 和 m 种颜色,用这些颜色给图的顶点着色,每个顶点一种颜色。如果要求G的每条边的两个顶点着不同颜色。给出所有可能的着色方案;如果不存在,则回答“NO”。

2.解析

设G有n个顶点,将顶点编号为 1,2,…,n,则搜索空间为深度n的m叉完全树,将颜色编号为1,2,…,m,结点1,x2,…,xk>表示顶点1的颜色x1,顶点2的颜色x2,…,顶点k的颜色xk.

按蛮力法的思想:
每个点都有m种着色,n个点共有mn种着色方式,遍历每种情况,才能得到满足要求的向量解。

利用回溯法的思想:
将着色解的生成过程类比为完全叉树的遍历过程,从根节点出发,每个节点都有m个子节点(m种着色),第i层代表第i个结点的所有着色情况,共有n层,判断每一个节点是否满足着色要求(边的两顶点着色不同)。

若满足要求则继续着色它的子节点直到全部顶点都着上色且满足要求;若不满足要求,该节点的所有子节点都不再将被遍历,回溯到该节点的父节点,并继续判断其兄弟节点(其他颜色)是否满足要求。

重复上述步骤,直至找到可行解或可能点遍历结束。

举个栗子

14回溯法——图的m着色问题_第1张图片

3.设计

void graphColor(int step) {
	if step == n then //存在可行的完整着色方案,打印方案
		for i ← 0 to n-1
			cout << color[i] << " ";
		end for i
		cout << endl;
		counts++;
	else 
		for k ← 1 to m
			color[step] = k;//step顶点尝试各种颜色着色
			if (check(step)) then//若改颜色着色可行,进行下一个顶点的着色
				graphColor(step+1);
			end if
			//不可行,回溯
			color[step] = 0;
		end for k
	end if
}

4.分析

graphColor()最坏情形复杂度=O(mn).

5.源码

点击前往Git

#include
#define N 100//最大顶点数

using namespace std;

int color[N] = {0};//各顶点颜色数组
int graph[N][N] = {0};//无向图的邻接矩阵
int n, m;//n为定点数,m为着色数
int counts=0;//可行方案总数

bool check(int step) {
	for (int i = 0; i < n; i++) {
		//如果两顶点连通且着色相同,着色不合理
		if (graph[step][i] == 1 && color[step] == color[i]) {
			return false;
		}
	}
	return true;
}

void graphColor(int step) {
	if (step == n) {//存在可行的完整着色方案,打印方案
		for (int i = 0; i < n; i++) {
			cout << color[i] << " ";
		}
		cout << endl;
		counts++;
	}
	else {
		for (int k = 1; k <= m; k++) {
			color[step] = k;//step顶点尝试各种颜色着色
			if (check(step)) {//若改颜色着色可行,进行下一个顶点的着色
				graphColor(step+1);
			}
			//不可行,回溯
			color[step] = 0;
		}
	}
}

int main() {

	/*输入:
		5 4
		0 1 1 1 0
		1 0 1 1 1
		1 1 0 1 0
		1 1 1 0 1
		0 1 0 1 0*/
	
	cout << "请分别输入定点数n和着色数m:" << endl;
	cin >> n >> m;
	cout << "请输入邻接矩阵:" << endl;
	int row, col, v;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			cin >> graph[i][j];
		}
	}
	graphColor(0);
	if (counts != 0)
		cout << "可行方案数为:" << counts << endl;
	else
		cout << "No" << endl;
	return 0;
}

14回溯法——图的m着色问题_第2张图片
14回溯法——图的m着色问题_第3张图片

你可能感兴趣的:(算法设计与分析基础)