问题描述:
给定无向连通图G=(V, E)和m种不同的颜色,用这些颜色为图G的各顶点着色,每个顶点着一种颜色。是否有一种着色法使G中相邻的两个顶点有不同的颜色。这个问题是图的m可着色判定问题。若一个图最少需要m种颜色才能使图中每条边连接的两个顶点着不同颜色,则称这个数m为该图的色数。求一个图的色数m的问题称为图的m可着色优化问题。
算法设计:
回溯法: 如果会了装载问题 和 0-1背包的回溯解法,这个题目容易解出。代码如下:
代码:
#include <bits/stdc++.h> using namespace std; int m; int pointnum; int edgenum; int sum = 0; int Graph[100][100]; int x[100]; void InPut() { int pos1, pos2; scanf("%d %d", &pointnum, &m); scanf("%d", &edgenum); memset(Graph, 0, sizeof(Graph)); for(int i = 1; i <= edgenum; ++i) { scanf("%d %d", &pos1, &pos2); Graph[pos1][pos2] = Graph[pos2][pos1] = 1; } } bool IsOk(int i) { for(int j = 1; j < i; ++j) if(Graph[i][j] == 1 && x[j] == x[i]) return false; return true; } void BackTrack(int i) { if(i > pointnum) { sum += 1; printf("方法 %d : ", sum); for(int j = 1; j <= pointnum; ++j) { printf("%d ", x[j]); } printf("\n"); return; } else { for(int j = 1; j <= m; ++j) { x[i] = j; if(IsOk(i)) BackTrack(i + 1); x[i] = 0; } } } void OutPut() { printf("一共有 %d 中绘色方案", sum); } int main() { InPut(); BackTrack(1); OutPut(); }
测试样例:
输入:
5 4
8
1 3
1 2
1 4
2 3
2 4
2 5
3 4
4 5
输出:
方法 1 : 1 2 3 4 1
方法 2 : 1 2 3 4 3
方法 3 : 1 2 4 3 1
方法 4 : 1 2 4 3 4
方法 5 : 1 3 2 4 1
方法 6 : 1 3 2 4 2
方法 7 : 1 3 4 2 1
方法 8 : 1 3 4 2 4
方法 9 : 1 4 2 3 1
方法 10 : 1 4 2 3 2
方法 11 : 1 4 3 2 1
方法 12 : 1 4 3 2 3
方法 13 : 2 1 3 4 2
方法 14 : 2 1 3 4 3
方法 15 : 2 1 4 3 2
方法 16 : 2 1 4 3 4
方法 17 : 2 3 1 4 1
方法 18 : 2 3 1 4 2
方法 19 : 2 3 4 1 2
方法 20 : 2 3 4 1 4
方法 21 : 2 4 1 3 1
方法 22 : 2 4 1 3 2
方法 23 : 2 4 3 1 2
方法 24 : 2 4 3 1 3
方法 25 : 3 1 2 4 2
方法 26 : 3 1 2 4 3
方法 27 : 3 1 4 2 3
方法 28 : 3 1 4 2 4
方法 29 : 3 2 1 4 1
方法 30 : 3 2 1 4 3
方法 31 : 3 2 4 1 3
方法 32 : 3 2 4 1 4
方法 33 : 3 4 1 2 1
方法 34 : 3 4 1 2 3
方法 35 : 3 4 2 1 2
方法 36 : 3 4 2 1 3
方法 37 : 4 1 2 3 2
方法 38 : 4 1 2 3 4
方法 39 : 4 1 3 2 3
方法 40 : 4 1 3 2 4
方法 41 : 4 2 1 3 1
方法 42 : 4 2 1 3 4
方法 43 : 4 2 3 1 3
方法 44 : 4 2 3 1 4
方法 45 : 4 3 1 2 1
方法 46 : 4 3 1 2 4
方法 47 : 4 3 2 1 2
方法 48 : 4 3 2 1 4
一共有 48 中绘色方案
部分截图: