图的m着色问题 解题报告

图的m着色问题
【问题描述】
       给定无向连通图G和m种不同的颜色。用这些颜色为图G的各顶点着色,每个顶点着一种颜色。如果有一种着色法使G中每条边的2个顶点着不同颜色,则称这个图是m可着色的。图的m着色问题是对于给定图G和m种颜色,找出所有不同的着色法。
【编程任务】
       对于给定的无向连通图G和m种不同的颜色,编程计算图的所有不同的着色法。
【输入格式】
       第1行有3个正整数n,k 和m,表示给定的图G有n个顶点和k条边,m种颜色。顶点编号为1,2,…,n。接下来的k行中,每行有2个正整数u,v,表示图G 的一条边(u,v)。
【输出格式】
       程序运行结束时,将计算出的不同的着色方案数输出。
【输入样例】
5 8 4
1 2
1 3
1 4
2 3
2 4
2 5
3 4
4 5
【输出样例】
48

【解题思路】
其实这道题刚开始依然没思路(搜索刚开始做得太不熟练,,,。。。求原谅),fye大爷再次典型梦中人!!!!
经大爷点拨之后这道题就非常清晰了。。。其实我们可以用到类似前面部落卫队的思路:仇敌关系和颜色关系其实可以用同一种表示方法;
f[i][j]表示与i相连的点有几个是颜色j;
因为同色的不能连在一起,所以f[i][j]为0时可取,非0时不可取;
因为周围有可能有很多个相同颜色的点,所以f数组必须是一个计数器(int),而不能是bool;
就这么着。。。

【代码】
#include
#include
#include
using namespace std;
int n,k,m,x,y,i,ans=0;
int a[1001][1001],f[1001][1001];

void dfs(int dep)//dep逐个点搜索
{
	int i,j;
	if (dep==n+1)
	{
		ans++;
		return;
	}
	for (i=1;i<=m;++i)//枚举m种颜色
	  if (!f[dep][i])//如果dep这个点周围没有i这种颜色,就说明这个点可以涂成颜色i
	  {
	  	for (j=1;j<=n;++j)
	  	  if (a[dep][j])
	  	    f[j][i]++;//那么把所有与dep相邻的点都+1
	  	dfs(dep+1);
	  	for (j=1;j<=n;++j)
	  	  if (a[dep][j])
	  	    f[j][i]--;//回溯一步
	  }
    return;
} 

int main()
{
	scanf("%d%d%d",&n,&k,&m);
	for (i=1;i<=k;++i)
	{
		scanf("%d%d",&x,&y);
		a[x][y]=1;//相连的关系记录一下
		a[y][x]=1;
	}
	dfs(1);
	printf("%d",ans);
	return 0;
}


你可能感兴趣的:(题解,搜索)