-
问题
图的m着色问题。给定无向连通图G和m种颜色,用这些颜色给图的顶点着色,每个顶点一种颜色。如果要求G的每条边的两个顶点着不同颜色。给出所有可能的着色方案;如果不存在,则回答“NO”。 -
解析
- 设计
bool ok(int c) //判断是否可以涂上该颜色
{
for(int k = 1; k <= n; k++)
{
if(graph[c][k] && color[c] == color[k]){
return false;
}
}
return true;
}
void backtrack(int cur) //回溯的过程
{
if(cur > n){
for(int i = 1; i <= n; i++){
cin>>color[i];
}
count++;
printf("\n");
}else{
for(int i = 1; i <= m; i++)
{
color[cur] = i;
if(ok(cur)){
backtrack(cur + 1);
}
color[cur] = 0;
}
}
}
-
分析
最坏的情况,有n个顶点,每个顶点有m种颜色,其有n-1个子节点
O(n) = n*mn-1/m-1=O(nmn) -
源码
#include <iostream>
#include <cstdio>
#include <fstream>
using namespace std;
int n, m; //n个顶点 m种颜色
int a = 1, b = 1; //输入时的顶点
int count = 0; //记录总方案数
int graph[20][20] = {0}; //记录无向图
int color[20] = {0}; //颜色
bool ok(int c) //判断是否可以涂上该颜色
{
for(int k = 1; k <= n; k++)
{
if(graph[c][k] && color[c] == color[k]){
return false;
}
}
return true;
}
void backtrack(int cur) //回溯的过程
{
if(cur > n){
for(int i = 1; i <= n; i++){
printf("%d ",color[i]);
}
count++;
printf("\n");
}else{
for(int i = 1; i <= m; i++)
{
color[cur] = i;
if(ok(cur)){
backtrack(cur + 1);
}
color[cur] = 0;
}
}
}
int main()
{
ifstream fin("input.txt");
fin >> n >> m;
cout << "输入的无向图为:" << endl;
while(fin >> a >> b && a != 0 && b != 0){
cout << a << " " << b << endl;
graph[a][b] = 1;
graph[b][a] = 1; //无向图记录两边
}
cout <<endl;
backtrack(1);
cout << "总共的方案数为:" << endl;
cout << count << endl;
system("pause");
return 0;
}
/*
input
5 3
1 2
1 4
1 5
2 3
2 5
4 5
0 0
*/