问题:
给定 无向连通图G=(V,E) 和 c种不同的颜色,用这些颜色为图G的各顶点着色,每个顶点着一种颜色。如果一个图最少需要c种颜色才能使图中每条边连接的2个顶点着不同颜色,则称c为该图的色数。
著名的 四色定理 就是指每个平面地图都可以只用四种颜色来染色,而且没有两个邻接的区域颜色相同。
求:给定图的顶点v,顶点间的边邻接关系c[][],颜色的数量c,一共有多少种着色方法?
这是一道非常典型的回溯题目。解法与“八皇后问题”一样。在填写每一个顶点的颜色时检查与相邻已填顶点的颜色是否相同。如果不同,则填上;如果相同(冲突),则另选一种;如果已没有颜色可供选择,则回溯到上一顶点。重复这一过程,直到所有顶点的颜色都已填上。
input
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
output
48
对于上面这图,颜色数量为4,顶点数为5,求得的解答树如下:
#include<iostream>
using namespace std;
int c[100][100]; //邻接矩阵
int color[100]; //记录每个顶点的颜色
int count,m,n; //count记录方案数 n个顶点 m种颜色
int Check(int k) //检查第i个顶点的颜色是否满足条件
{
for(int i=1;i<=k;i++)
{
if(c[k][i]==1&&color[i]==color[k]) //k与i之间相连并且i顶点的颜色与k顶点的颜色相同
return 0;
}
return 1;
}
void GraphColor(int step)
{
if(step==n+1) //表示前面所有的顶点颜色都已经填完
{
for(int i=1;i<=n;i++)
printf("%d ",color[i]);
count++;
printf("\n");
return ;
}
else
{
for(int i=1;i<=m;i++)
{
color[step]=i; //首先将这个顶点颜色换为i
if(Check(step)==1) //检查是否符合条件
{
GraphColor(step+1); //符合条件则走下一步
}
color[step]=0; //回溯 置为0
}
}
}
int main(void)
{
int a,b;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
cin>>c[i][j];
}
GraphColor(1);
printf("%d",count);
return 0;
}