码迷,mamicode.com
首页 > 其他好文 > 详细

图的m着色问题

时间:2015-07-11 12:07:49      阅读:200      评论:0      收藏:0      [点我收藏+]

标签:

一. 问题描述

给定无向连通图G和m种不同的颜色。用这些颜色为图G的各顶点着色,每个顶点着一种颜色。是否有一种着色法使G中每条边的2个顶点着不同颜色。这个问题是图的m可着色判定问题。若一个图最少需要m种颜色才能使图中每条边连接的2个顶点着不同颜色,则称这个数m为该图的色数。求一个图的色数m的问题称为图的m可着色优化问题。

技术分享

给定图G=(V,E)和m种颜色,如果这个图不是m可着色,给出否定回答;如果这个图是m可着色的,找出所有不同的着色法。

二. 问题分析

1> 解向量:(x1, x2, … , xn)表示顶点i所着颜色x[i]

2> 解空间树:子集树,下图为n=3,m=3时问题的解空间树

3> 剪枝函数:顶点i与已着色的相邻顶点颜色不重复。约束函数

技术分享

三. 算法实现

/** 
图的m着色问题
输入示例
5 8 5
1 2
1 3
1 4
2 3
2 4
2 5
3 4
4 5
*/
#include <iostream>
using namespace std;

class Color
{
	friend int mColoring(int,int,int**);
	private:
		bool ok(int k);
		void backtrack(int t);
		int n,			// 图的顶点数
			m,			// 可用颜色数 
			**a,		// 图的邻接矩阵
			*x,			// 当前解
			sum;		// 当前已找到的可m着色方案数
};

bool Color::ok(int k)
{
	// 检查颜色可用性
	for (int j=1; j<k; j++)
	{
		if ((a[k][j]==1)&&(x[j]==x[k]))
			return false;
	}
	return true;
}

/* 回溯算法 子集树 */
void Color::backtrack(int t)
{
	if (t>n)	// 搜索到叶子结点
	{
		sum++;
		for (int i=1; i<=n; i++)
		{
			cout << x[i] << " ";
		}
		cout << endl;
	}
	else
	{
		for (int i=1; i<=m; i++)
		{
			x[t] = i;
			if (ok(t))
			{
				backtrack(t+1);
			}
			x[t] = 0;
		}
	}
}

int mColoring(int n, int m, int** a)
{
	Color C;
	// 初始化C
	C.n = n;
	C.m = m;
	C.a = a;
	C.sum = 0;
	int *x = new int[n+1];
	for (int i=0; i<=n; i++)
	{
		x[i] = 0;
	}
	C.x = x;
	C.backtrack(1);
	delete []x;
	return C.sum;
}

void main()
{
	int e,m,n,u,v;

    int** a = new int*[100];
    for(int k=0; k<100; k++)
	{
        a[k] = new int[100];
	}

	while(1)
	{
		cout << "输入顶点数n、边数e和着色数m:" << endl;
		cin >> n >> e >> m;
		cout << "请输入无向图的边(如边(1,2)则输入1 2):" << endl;
		for (int i=0; i<e; i++)
		{
			cin >> u >> v;
			a[u][v] = 1;
			a[v][u] = 1;
		}
		cout << "可行的着色法:" << endl;
		int sum = mColoring(n,m,a);
		cout << "总共有" << sum << "种着色法" << endl;
	}
}

图的m着色问题

标签:

原文地址:http://www.cnblogs.com/xwz0528/p/4638225.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!