题目描述
给定无向连通图G=(V, E)和m种不同的颜色,用这些颜色为图G的各顶点着色,每个顶点着一种颜色。是否有一种着色法使G中相邻的两个顶点有不同的颜色?
这个问题是图的m可着色判定问题。若一个图最少需要m种颜色才能使图中每条边连接的两个顶点着不同颜色,则称这个数m为该图的色数。求一个图的色数m的问题称为图的m可着色优化问题。
编程计算:给定图G=(V, E)和m种不同的颜色,找出所有不同的着色法和着色总数。
输入描述
第一行是顶点的个数n(2≤n≤10),颜色数m(1≤m≤n)。
接下来是顶点之间的相互关系:a b
表示a和b相邻。当a,b同时为0时表示输入结束。
输出描述
输出所有的着色方案,表示某个顶点涂某种颜色号,每个数字的后面有一个空格。最后一行是着色方案总数。
示例1
输入:
5 4
1 3
1 2
1 4
2 3
2 4
2 5
3 4
4 5
0 0输出:
1 2 3 4 1
1 2 3 4 3
1 2 4 3 1
1 2 4 3 4
1 3 2 4 1
1 3 2 4 2
1 3 4 2 1
1 3 4 2 4
1 4 2 3 1
1 4 2 3 2
1 4 3 2 1
1 4 3 2 3
2 1 3 4 2
2 1 3 4 3
2 1 4 3 2
2 1 4 3 4
2 3 1 4 1
2 3 1 4 2
2 3 4 1 2
2 3 4 1 4
2 4 1 3 1
2 4 1 3 2
2 4 3 1 2
2 4 3 1 3
3 1 2 4 2
3 1 2 4 3
3 1 4 2 3
3 1 4 2 4
3 2 1 4 1
3 2 1 4 3
3 2 4 1 3
3 2 4 1 4
3 4 1 2 1
3 4 1 2 3
3 4 2 1 2
3 4 2 1 3
4 1 2 3 2
4 1 2 3 4
4 1 3 2 3
4 1 3 2 4
4 2 1 3 1
4 2 1 3 4
4 2 3 1 3
4 2 3 1 4
4 3 1 2 1
4 3 1 2 4
4 3 2 1 2
4 3 2 1 4
Total=48
算法分析
深搜,具体步骤是将cur=1传入backtrack(),即从第一个开始涂色。
涂的时候从颜色1开始到m,每当涂上一个色,要用ok(cur)判断第cur个点是否可以涂这个色,不可以的话就不再往下涂了,改试另一个颜色,可以的话就继续。
当cur>n的时候即前n个点都涂完了,然后输出结果并cou++计数。
提交代码:
#include<iostream>
#include<vector>
using namespace std;
int total = 0;
int n, m;
vector<vector<int>> edge;
vector<int> color;
bool ok(int cur)
{
for (int i = 1; i <= n; ++i)
if (edge[cur][i] == 1 && color[cur] == color[i])
return false;
return true;
}
void bfs(int cur)
{
if (cur > n) {
for (int i = 1; i <= n; ++i)
cout << color[i] << " ";
++total;
cout << endl;
}
else {
for (int i = 1; i <= m; ++i) {
color[cur] = i;
if (ok(cur))
bfs(cur + 1);
color[cur] = 0;
}
}
}
int main()
{
cin >> n >> m;
edge = vector<vector<int>>((n+1)*(n+1), vector<int>((n+1)*(n+1), 0));
color = vector<int>(n+1, 0);
int i, j;
while (cin >> i >> j && i!=0 && j!=0) {
edge[i][j] = 1;
edge[j][i] = 1;
}
bfs(1);
cout << total << endl;
return 0;
}