日撸代码300行:第35天(图的 m 着色问题)

代码来自闵老师”日撸 Java 三百行(31-40天)“,链接:https://blog.csdn.net/minfanphd/article/details/116975772

**问题描述:**给定无向连通图G和m种不同的颜色。用这些颜色为图G的各顶点着色,每个顶点着一种颜色。是否有一种着色法使G中每条边的2个顶点着不同颜色。这个问题是图的m可着色判定问题。若一个图最少需要m种颜色才能使图中每条边连接的2个顶点着不同颜色,则称这个数m为该图的色数。求一个图的色数m的问题称为图的m可着色优化问题。

	/**
	 * *****************************************************************
	 * Coloring.Output all possible schemes.
	 * 
	 * @param paraNumColors   The number of colors.
	 * *****************************************************************
	 */
	public void coloring(int paraNumColors) {
		int tempNumNodes = connectivityMatrix.getRows();
		int[] tempColorScheme = new int[tempNumNodes];
		Arrays.fill(tempColorScheme, -1);
		
		coloring(paraNumColors, 0, tempColorScheme);
	}//of coloring
	
	/**
	 * ******************************************************************
	 * Coloring. Output all possible schemes.
	 * 
	 * @param paraNumColors   The number of colors.
	 * @param paraCurrentNumNodes    The number of nodes that have been colored.
	 * @param paraCurrentColoring    The array recording the coloring scheme.
	 * ******************************************************************
	 */
	public void coloring(int paraNumColors, int paraCurrentNumNodes, int[] paraCurrentColoring) {
		// Step 1. Initialize.
		int tempNumNodes = connectivityMatrix.getRows();

		//System.out.println("coloring: paraNumColors = " + paraNumColors + ", paraCurrentNumNodes = "
				//+ paraCurrentNumNodes + ", paraCurrentColoring" + Arrays.toString(paraCurrentColoring));
		// A complete scheme.
		if (paraCurrentNumNodes >= tempNumNodes) {
			System.out.println("Find one:" + Arrays.toString(paraCurrentColoring));
			return;  //自己写的时候少了return,数组越界了
		}//of if
		
		for (int i = 0; i < paraNumColors; i++) {
			
			paraCurrentColoring[paraCurrentNumNodes]= i;
			
			if (!colorConflict(paraCurrentNumNodes + 1, paraCurrentColoring)) {
				coloring(paraNumColors, paraCurrentNumNodes + 1, paraCurrentColoring);
			}//of if
		}//of for i
		
	}//of coloring
	
	/**
	 * ****************************************************************
	 * Coloring conflict or not. Only compare the current last node
	 * with previous ones.
	 * 
	 * @param paraCurrentNumNodes  The current number of nodes.
	 * @param paraColoring   The current coloring scheme.
	 * @return   Conflict or not.
	 * ****************************************************************
	 */
	public boolean colorConflict(int paraCurrentNumNodes, int[] paraColoring) {
		for (int i = 0; i < paraCurrentNumNodes - 1; i++) {
			// No direct connection.
			if (connectivityMatrix.getData()[paraCurrentNumNodes -1][i] == 0) {
				continue; 
			}//of if
			
			if (paraColoring[paraCurrentNumNodes - 1] == paraColoring[i]) {
				//It has the same color as the previous nodes.
				return true;
			}//of if
		}//of for i
		return false;
	}//of colorConflict
	
	public static void coloringTest() {
		int[][] tempMatrix = {{0, 1, 1, 0}, {1, 0, 0, 1}, {1, 0, 0, 0}, {0, 1, 0, 0}};
		Graph tempGraph = new Graph(tempMatrix);
		
		//tempGraph.coloring(2);
		tempGraph.coloring(3);
	}//of coloringTest
	
	/**
	 * ****************************************************************
	 * The entrance of program.
	 * @param args   Not used now.
	 * ****************************************************************
	 */
	public static void main(String args[]) {
		//Graph tempGraph = new Graph(3);
		//System.out.println(tempGraph);
		
		//getConnectivityTest();
		//breadthFirstTraversalTest();
		//depthFirstTraversalTest();
		
		coloringTest();
	}//of main

思考两个问题:
(1)自己写程序的时候,少写了一个return,导致数组越界。
如果没有return,一直给节点着色,总会超过声明的数组长度(tempNumNodes)。paraCurrentColoring[paraCurrentNumNodes]= i;就越界了。
(2)为啥会输出所有的着色方案,感觉代码只是找到一个着色方案,循环在哪里?
仔细想了一下,循环就是for实现的。原本以为for是为了解决着色问题,为了填充不同的颜色。其实是为了控制起始节点的颜色,然后后面的节点会分别着与之前节点不同的颜色。这样就实现了循环输出不同的方案。这里也涉及到上面return的问题,return会回退到下一个方案。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在C语言中,着色问题图论中的一个问题,特别是涉及到有向或无向的顶点着色问题,比如经典的四色定理,即任何简单平面都能用不多于四种颜色进着色,使得相邻的顶点颜色不同。回溯法(Backtracking)是一种常用的方法来解决这类组合优化问题,包括着色问题。 回溯算法步骤大致如下: 1. 初始化:选择一个未被着色的顶点,将其设为当前颜色(如第1种颜色)。 2. 剪枝:检查当前节点的邻居是否与当前颜色冲突。如果冲突,尝试下一个颜色;如果所有颜色都试过且都冲突,就回溯到上一个节点并改变其颜色。 3. 递归:对当前节点的未访问邻居重复以上步骤,直到所有的顶点都被着色或者无法找到一种可着色方案为止。 4. 结束条件:当所有顶点都被正确着色且没有冲突时,找到了一个有效的着色方案。 对于具体实现,你需要创建一个递归函数,用于尝试给每个顶点着色,同时维护一个颜色列表和一个已访问列表。在递归过程中,你可以使用一个栈来存储待检查的状态,回溯时从栈中弹出状态进修改。 回溯法的关键在于剪枝策略,也就是如何有效地判断当前状态下是否存在解决方案。对于顶点着色问题,一种常见的剪枝策略是使用邻接矩阵或邻接表来快速查找冲突。 如果你想了解如何用C语言编写具体的回溯算法来解决着色问题,我可以提供一个简化版的伪代码示例,但完整的代码实现会相当复杂,并且会依赖于具体的数据结构和库。是否有兴趣看一个简单的代码框架?如果有,请告诉我,或者我可以直接解释算法的原理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值