本文参考https://blog.youkuaiyun.com/kevin_cyj/article/details/50385575
问题描述与思想概述
(1)、问题的提出
给定无向连通图G和m种不同的颜色。用这些颜色为图G的各顶点着色,每个顶点着一种颜色。是否有一种着色法使G中每条边的2个顶点着不同颜色。这个问题是图的m可着色判定问题。若一个图最少需要m种颜色才能使图中每条边连接的2个顶点着不同颜色,则称这个数m为该图的色数。求一个图的色数m的问题称为图的m可着色优化问题。
输入:无向图,m
输出:如果能,则输出方案
四色问题是m图着色问题的一个特例,根据四色原理,证明平面或球面上的任何地图的所有区域都至多可用四种颜色来着色,并使任何两个有一段公共边界的相邻区域没有相同的颜色。这个问题可转换成对一平面图的4-着色判定问题(平面图是一个能画于平面上而边无任何交叉的图)。将地图的每个区域变成一个结点,若两个区域相邻,则相应的结点用一条边连接起来。多年来,虽然已证明用5种颜色足以对任一幅地图着色,但是一直找不到一定要求多于4种颜色的地图。直到1976年这个问题才由爱普尔,黑肯和考西利用电子计算机的帮助得以解决。他们证明了4种颜色足以对任何地图着色。
(2)、问题的处理
如果把每一个区域收缩为一个顶点,把相邻两个区域用一条边相连接,就可以把一个区域图抽象为一个平面图。
用m种颜色为图中的每个顶点着色,要求每个顶点着一种颜色,并使相邻两顶点之间有着不同的颜色
如图:
一个例子
着色问题的解空间树为:
可以看到约束函数为:i点有m种着色可能性,但若与某个已着色的点相连且颜色相同,则不选择这种着色可能性
3、练习题
https://www.luogu.org/problem/P2819
代码:
#include <iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
int n;//n个节点
int m;//m种颜色
int mm[100][100];//记录图的邻接矩阵
int x[100];//记录树的一条枝,即图着色的一种可能性,x[i]=1,2,3..k..n代表第节点i颜色为k
int bestx[100];
int sum=0;//用来记录当前可行的着色方案
//分析本题的约束函数为两节点相连且同种颜色时,不会继续往下发展这种可能性
bool ok(int i)
{
int j;
for(j=1;j<=n;j++)
{
if((mm[i][j]==1)&&(x[i]==x[j]))//我到底和哪些节点相连且颜色一样
{
return false;
}
}
return true;
}
void dfs(int i)
{
int j;
if(i>n)
{
sum++;
for(j=1;j<=n;j++)
{
bestx[j]=x[j];//记录一条枝(记录一种着色的可能性)
}
}
else
{
for(j=1;j<=m;j++)//在i节点处检测它自己可能填的m种可能性
{
x[i]=j;//i节点选定了一种颜色
if(ok(i))//通过约束函数去掉不合理的颜色可能性
{
dfs(i+1);//活节点转移到下一层的第i+1个节点
}
x[i]=0;//无实义,为i继续换别的颜色可能性
}
}
}
int main()
{
int t,k;
int i,j;
scanf("%d %d %d",&n,&k,&m);//k是k条边
for(t=0;t<k;t++)
{
scanf("%d %d",&i,&j);
mm[i][j]=1;
mm[j][i]=1;
}
dfs(1);
printf("%d",sum);
return 0;
}