题目 图的m着色问题
题目背景
给定无向连通图 G 和 m 种不同的颜色。用这些颜色为图 G 的各顶点着色,每个顶点着一种颜色。如果有一种着色法使 G 中每条边的2个顶点着不同颜色,则称这个图是 m 可着色的。图的 m 着色问题是对于给定图 G 和 m 种颜色,找出所有不同的着色法。
题目描述
对于给定的无向连通图 G 和 m 种不同的颜色,编程计算图的所有不同的着色法。
输入格式
第1行有3个正整数n,k 和m,表示给定的图 G 有 n 个顶点和 k 条边,m 种颜色。顶点编号为1,2,…,n。接下来的 k 行中,每行有 2 个正整数u,v,表示图 G 的一条边(u,v)。
输出格式
程序运行结束时,将计算出的不同的着色方案数输出。
样例 #1
样例输入 #1
5 8 4
1 2
1 3
1 4
2 3
2 4
2 5
3 4
4 5
样例输出 #1
48
提示
n<=100;k<=2500;
在 n 很大时保证 k 足够大。
保证答案不超过20000。
分析
用邻接矩阵f[][]
二维数组存储图
用数组color[]
存储每个结点的颜色,初始化为0
对每个点进行 for 循环,猜测赋值的颜色,然后递归对下一个点进行猜测
AC代码
#include<stdio.h>
#include<cstring>
int n ,k,m,x,y;
bool f[105][105];//存两个点是否连通
int color[105];//存每个点的颜色
int num=0;
bool check(int sum) {//检查与该点相连的点的颜色是否重复了
int i;
for(i=1; i<=sum; i++) {
if(f[i][sum]==true && color[i]==color[sum]) {
return false;//重复了
}
}
return true;//没有重复
}
void dfs(int s) {
if(s>n) { //说明所有点的颜色都赋值完了
num++;
return;
}
int j;
for(j=1; j<=m; j++) { //颜色的种类,给当前的点什么颜色呢?-for循环挑
color[s]=j;//将点s赋值为颜色j
if(check(s)==true)//不冲突就对下一个点上色
dfs(s+1);
color[s]=0;//如果冲突或者清除前面的赋值操作,赋值为0
}
}
int main() {
//输入数据,存储图像
scanf("%d%d%d",&n,&k,&m);
int i;
for(i=1; i<=k; i++) {
scanf("%d%d",&x,&y);
f[x][y]=true;//有边
f[y][x]=true;
}
dfs(1);//开始给第一个点赋予颜色
printf("%d\n",num);
return 0;
}