题目描述
给定无向连通图G=(V,
E)和m种不同的颜色,用这些颜色为图G的各顶点着色,每个顶点着一种颜色。是否有一种着色法使G中相邻的两个顶点有不同的颜色?
这个问题是图的m可着色判定问题。若一个图最少需要m种颜色才能使图中每条边连接的两个顶点着不同颜色,则称这个数m为该图的色数。求一个图的色数m的问题称为图的m可着色优化问题。
编程计算:给定图G=(V, E)和m种不同的颜色,找出所有不同的着色法和着色总数。输入
第一行是顶点的个数n(2≤n≤10),颜色数m(1≤m≤n)。 接下来是顶点之间的相互关系:a b
表示a和b相邻。当a,b同时为0时表示输入结束。输出
输出所有的着色方案,表示某个顶点涂某种颜色号,每个数字的后面有一个空格。最后一行是着色方案总数。
题解思路
对m种颜色编号为1,2,…,m,由于每个顶点可从m种颜色中选择一种颜色着色,如果无向连通图G=(V, E)的顶点数为n,则解空间的大小为m的n次方种,解空间是非常庞大的,它是一棵m叉树。
当n=3,m=3时的解空间树:
图的m着色问题的约束函数是相邻的两个顶点需要着不同的颜色,但是没有限界函数。
假设无向连通图G=(V, E)的邻接矩阵为a,如果顶点i和j之间有边,则a[i][j]=1,否则a[i][j]=0。
设问题的解向量为X (x1, x2 , …, xm) ,其中xi∈{1, 2, …, m},表示顶点i所着的颜色是x[i],即解空间的每个结点都有m个儿子。
#include <iostream>
#include<bits/stdc++.h>
#define N 100
#define INF 0x3f3f3f3f
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(i,a,n) for(int i=a;i<=n;i++)
typedef long long ll;
using namespace std;
#define NUM 100
int n;//图的顶点数量
int m;//可用颜色数量
int a[NUM][NUM];//图的邻接矩阵
int x[NUM];//当前的解向量
int sum ;//已经找到的可m着色的方案数量
bool Same(int t)//约束函数
{
int i;
for(i=1;i<=n;i++)
{
if((a[t][i]==1)&&(x[i]==x[t]))//这一行,相邻的
return false;
}
return true;
}
void Backtrack(int t)//搜索t层结点
{
int i;
if(t>n)
{
sum++;
for(i=1;i<=n;i++)
{
cout<<x[i]<<" ";
}
cout<<endl;
}
else
{
for(i=1;i<=m;i++)
{
x[t]=i;//颜色值
if(Same(t))Backtrack(t+1);
x[t]=0;//恢复
}
}
}
int main()
{
cin>>n>>m;
int i,j;
while(cin>>i>>j&&i&&j)
{
a[i][j]=a[j][i]=1;
}
Backtrack(1);
cout<<sum<<endl;
}