欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

深搜 图的M着色问题

程序员文章站 2022-06-09 18:05:23
...

吉林大学大二学生 东北师范大学附属中学OJ jinxi20111 2019.05.16

题目描述

给定无向连通图G和M种不同的颜色,用这些颜色为图G的各顶点着色,每个顶点着一种颜色。如果有一种着色法使G中每条边的2个顶点着不同的颜色,则称这个图是M可着色的。图的M着色问题是对于给定图G和M种颜色,找出所有不同的着色法。

对于给定的无向连通图G和M种不同的颜色,编程计算图的所有不同的着色法。

输入

第一行有3个正整数N,K和M,表示给定的图G有N个顶点和K条边,M种颜色。顶点编号为1,2……,N。接下来的K行中,每行有2个正整数U,V,表示图G的一条边(U,V)。

 数据范围:1<N<=100    1<K<=2500     1<M<=6

输出

不同的着色方案数

样例输入

5 8 4
1 2
1 3
1 4
2 3
2 4
2 5
3 4
4 5

样例输出

48

分析过程

在东北师大附中的OJ上刚过的一道题

用将近一周烦恼,解决就用了15min

简述一下我 silly B 的烦恼过程


看到一道题,我习惯直奔数据范围

N为100,M为6 ,深搜量Nm最大为1W亿

OK,炸了

直接排除 直接打表和简单深搜


然后就是怀疑人生阶段(持续一周)

我在想出思路之前,基本上不会去查题解

于是我下意识去构建了图

图的存储方式,最基本的就是邻接矩阵和邻接表

在这道题中,显然很难取舍

那就分开考虑,首先先做邻接矩阵

一个100平方的矩阵显然不大。我就直接写了个二维数组。接下来的深搜过程可给老子烦坏了。

我的思路是,染好第一个色之后,给它相连的点一个无法染色的标识。

我可以说,当时我想的很美,因为这样做成功了的话,我的dfs里面就干干净净只有一个deep,并且代码量也会很小。

只能说,菜鸡你想的太美律师函警告

因为染色过程中,势必会出现多个点连接一个点,这个时候,如何取消染色(回溯)成了一个难以解决的问题。

谁做谁知道。至少当时我没做出来。

然后我就去做了个邻接表,打算用宽搜BFS去做。

然而,找前置点成了问题,即你根本不知道为什么不能染某个色。

代码不粘了,太二了,又臭又长又超时。

两个都解不了。

懵了。

于是我去北苑一公寓三楼西北角的洗手间的第三个坑蹲了一会

有点便秘,没蹲出来(双关?)

没办法,暂时放弃。

在将近一周之中,我想了很多办法。比如,将边进行排序,用来节省生成邻接表的时间。(后来发现这很智障

又比如,生成树,然后逐层染色。结果仔细读读题,根本没说没有回路,,也就说有可能改不成树。

今天实验课,我闲得没事,在北苑一公寓三楼西北角的洗手间的第三个坑蹲坑的时候,把题拿了出来。

艹,这题跟怎么存图没啥关系,,


其实这道题的优化是有一些的。但是思路对了,应该是用不上优化的。

我们需要做的是,把图存到初始化为False的邻接矩阵中,然后用回溯法去遍历Color

回溯遍历?

如下:

代码一,条件分别代表 相连 同色 已染色

//回溯条件 相连 同色 已染色
if ((g[deep][j])&&(c[deep]==c[j])&&(c[deep]!=0))
{
	flag=false;
}

代码二,回溯行为,取消染色

if (flag)
{	
	dfs(deep+1);
}
c[deep]=0;

这样做,其实纯粹是灵光乍现。因为我一直觉得这样做既浪费时间,也浪费空间。但在这道题里,很巧妙的在空间和时间中找到了一个平衡点。深搜100个点,找点的过程是6*1002 ,不大,存边的矩阵是1002 ,也不大。可以说是非常完美(牛气叉腰!)

下面是AC代码展示

//吉林大学大二学生 东北师范大学附属中学OJ jinxi20111 2019.05.07

//MythCoffee 图的M着色问题
#include<iostream>
using namespace std;
int n,k,m,ans;
int g[101][101],c[101];
void dfs(int deep)
{
	if (deep>n)
	{
		ans++;
	}
	else
	{
		int i,j;
		bool flag;
		for(i=1;i<=m;i++)
		{
			c[deep]=i;
			flag=true;
			j=1;
			while ((j<=n)&&(flag))
			{
				if ((g[deep][j])&&(c[deep]==c[j])&&(c[deep]!=0))
				{
					flag=false;
				}
				j++;
			}
			if (flag)
			{	
				dfs(deep+1);
			}
			c[deep]=0;
		}
	}
	
}
int main()
{
	int s,j,t1,t2;
	cin>>n>>k>>m;
	for(s=1;s<=n;s++)
	{
		for(j=1;j<=n;j++)
		{
			g[s][j]=false;
		}
	}
	for(s=1;s<=k;s++)
	{
		cin>>t1>>t2;
		g[t1][t2]=true;
		g[t2][t1]=true;
	}
	dfs(1);
	cout<<ans;
	return 0;
}