持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情
图的 m 着色问题
问题描述
给定无向连通图G和m种不同的颜色。用这些颜色为图G的各顶点着色,每个顶点着一种颜色。如果有一种着色法使G中每条边的2个顶点着不同颜色,则称这个图是m可着色的。图的m着色问题是对于给定图G和m种颜色,找出所有不同的着色法
分析:
设M[i]= x(x= 0,1,2,..m )代表第i节点的颜色x; m=3(以下图为例,红色代表冲突)
M[0] = 0,M[1]={0,1,2}, M[2]={0,1,2} 进行颜色排列组合{0,1,1},{0,1,2},{0,2,1},{0,2,2}
M[0] = 1, M[2]={0,1,2},M[2]={0,1,2}进行颜色排列组合{1,0,0},{1,0,2},{1,2,0},{1,2,2}
M[0] = 2, M[2]={0,1,2},M[2]={0,1,2}进行颜色排列组合{2,0,0},{2,0,1},{2,1,0},{2,1,1}
在图的着色过程中,我们需要判断是否是邻接点(颜色是否冲突)。
其中也有递归的思想在里面,例如我确定了0节点的颜色,我去判断剩下其他节点的颜色。在1,2节点颜色,我确定了1节点颜色,又去判断3节点的颜色。
刚开始我还不理解 解空间树,但是在经过上面自己这样手动的分析之后,再去理解解空间树就一目了然。根据上图,画出了空间树。 虽然理解了,但感觉理论到实践还是有一定的距离,多敲。
代码
在实现着色代码中,结合上面空间树,我一个节点一个节点到最深,判断着色是否冲突,判断完,又回收到上一个节点又往下,最后把所有的空间树判断完。即可找出着色的所有可能。以下这段代码就在尝试所有的可能,其中的colorConflict方法则是在判断是否是相邻边?这个颜色是否有冲突(即是相邻节点,颜色是否一样),只有非冲突,进行递归所有可能取得的颜色排列组合,退出一次递归的出口则则是:完成一次排列组合。这个过程有点儿像树的深度遍历(回溯)
for (int i = 0; i < paraNumColors; i++) {
paraCurrentColoring[paraCurrentNumNodes] = i;
if (!colorConflict(paraCurrentNumNodes + 1, paraCurrentColoring)) {
coloring(paraNumColors, paraCurrentNumNodes +1 , paraCurrentColoring);
}
}
总结:
今天结合m着色问题去将排列组合问题转换为空间树去求解,在解空间树时,即去遍历所有的节点并需要判断是否符合组合条件。