回溯法经典例题--求解图的m着色问题--C语言

问题描述:

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

求解:

        给无向图上色且相邻顶点不能上同样的色,把它看作m叉树后,类似于红黑树。

        

        我们把颜色用数字代替。有多少种颜色,每个节点就有多少个孩子,每一层对应当前节点选择上的色.

        当到达叶子节点时,表示所有节点已经按照要求选好了颜色,也就是出口。

         

 

代码:

        g是图的邻接矩阵,p存储i节点涂的颜色代号,n为节点个数,i为当前递归节点,m颜色数量

#include<stdio.h>
#include<iostream>
using namespace std;
#define max 10
int num = 0;
bool paintable(int g[max][max], int p[max], int n,int i) {
	for (int j = 1; j <= n; j++) {
		if (g[i][j] == 1 && p[i] == p[j])
			return false;
	}
	return true;
}
void dfs(int g[max][max],int p[max], int n, int m,int i) {
	if (i > n) {
		num++;
	}
	else {
		for (int j = 1; j <= m; j++) {
			p[i] = j;
			if (paintable(g, p, n, i))
				dfs(g, p, n, m, i + 1);
			p[i] = 0;
		}
	}
}
int main() {
	int n = 4;
	int m = 3;
	int g[max][max];
	int paint[max];
	memset(paint, 0, sizeof(paint));
	memset(g, 0, sizeof(g));
	g[1][2] = 1;g[1][3] = 1;g[1][4] = 1;
	g[2][1] = 1;
	g[3][1] = 1; g[3][4] = 1;
	g[4][1] = 1; g[4][3] = 1;
	dfs(g, paint, n, m, 1);
	cout << num;
	return 0;
}

回溯法是一种常用的解决问题算法思想。对于n后问题,可以使用回溯法求解。n后问题是指在一个n×n的棋盘上放置n个皇后,使得任意两个皇后都不在同一行、同一列或同一斜线上。以下是C语言实现的n后问题的代码: ```c #include <stdio.h> #include <stdbool.h> #define N 8 // 棋盘大小为8 int queen[N] = {0}; // 存放皇后所在列的数组 bool col[N] = {false}; // 判断列是否有皇后 bool left[N * 2 - 1] = {false}; // 判断左斜线是否有皇后 bool right[N * 2 - 1] = {false}; // 判断右斜线是否有皇后 void print_result() // 输出结果 { for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (j == queen[i]) { printf("Q "); } else { printf(". "); } } printf("\n"); } printf("\n"); } void search(int row) // 搜索皇后的位置 { if (row == N) // 找到解 { print_result(); // 输出结果 return; } for (int i = 0; i < N; i++) // 遍历列 { if (!col[i] && !left[row + i] && !right[N - 1 + row - i]) // 判断该位置是否可以放置皇后 { queen[row] = i; // 记录皇后所在列 col[i] = true; // 记录该列已有皇后 left[row + i] = true; // 记录左斜线已有皇后 right[N - 1 + row - i] = true; // 记录右斜线已有皇后 search(row + 1); // 继续搜索下一行 col[i] = false; // 回溯 left[row + i] = false; // 回溯 right[N - 1 + row - i] = false; // 回溯 } } } int main() { search(0); // 从第0行开始搜索 return 0; } ``` M着色问题是指在一个无向中对每个节点进行着色,使得相邻的节点颜色不同。以下是C语言实现的M着色问题的代码: ```c #include <stdio.h> #include <stdbool.h> #define N 5 // 的节点数 #define M 3 // 颜色数 bool graph[N][N] = { // 无向的邻接矩阵 { false, true, true, true, false }, { true, false, true, false, true }, { true, true, false, true, true }, { true, false, true, false, true }, { false, true, true, true, false } }; int color[N] = {0}; // 存放节点的颜色 bool check(int node, int c) // 判断节点能否被着色 { for (int i = 0; i < N; i++) { if (graph[node][i] && c == color[i]) // 如果该节点与相邻节点颜色相同,则无法着色 { return false; } } return true; } void print_result() // 输出结果 { for (int i = 0; i < N; i++) { printf("%d ", color[i]); } printf("\n"); } void search(int node) // 搜索节点的颜色 { if (node == N) // 找到解 { print_result(); // 输出结果 return; } for (int i = 0; i < M; i++) // 遍历颜色 { if (check(node, i)) // 判断该节点能否被着色 { color[node] = i; // 记录节点的颜色 search(node + 1); // 继续搜索下一个节点 color[node] = 0; // 回溯 } } } int main() { search(0); // 从第0个节点开始搜索 return 0; } ``` 以上是回溯法解决n后问题和M着色问题的C语言实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值