题目4图着色问题
给定一个无向图G=(V,E),其中V为顶点集合,E为边集合,图着色问题即为将V分为K个颜色组,每个组形成一个独立集,即其中没有相邻的顶点。器优化版本是希望获得最小的K值。
解题思路
本题与前几道题相比最大的不同点是,待分配的对象是可变的,如果是给出固定的颜色种类和一个无向图,球有多少种着色方法时,那就完全和n皇后问题是一种思想了,连数据结构都可以说是一模一样,但是这题求的是最少使用的颜色总数,可以定义一个sum来存放完成一次深度搜索时求得的使用的颜色总数,用mins来记录最小的颜色数。求每个点的颜色时,先用已有的每个颜色来试探,有符合条件的颜色时,sum就不用加一,记录此时sum的值便于回溯,然后递归调用函数求下一个点的颜色,但是如果已有的所有颜色都试探失败,这个时候sum就需要加一。在递归出口比较每次求得的总颜色数,每次都取最小的,进而求出最小的颜色数。
#include<iostream>
using namespace std;
int G[50][50]; //保存无向图
int color[50]; //存放每个点的颜色
int sum=0; //需要的颜色总数
int mins=999999; //需要的最少的颜色数
int N; //点的总个数
//检查点第i+1个点是否能放颜色c
bool check(int i,int c){
bool flag=true;
for(int j=0;j<i;j++){
if(G[j][i]==1){ //前面与第i+1个点直接相连的点
if(color[j]==c) //相连的点有颜色c
flag=false;
}
}
return flag;
}
//问题求解
void dfs(int i){
if(i>N-1){ //递归出口
if(sum<mins)
mins=sum; //记录最小颜色数
}
else{
//对第i+1个结点,尝试已使用的所有颜色
int find=0; //标记能否在已有颜色中找到可以使用的颜色
for(int j=0;j<sum;j++){
if(check(i,color[j])){
find=1;
int sum1=sum;
color[i]=color[j]; //第i+1个点和第j+1个点颜色相同
dfs(i+1); //求下一个点的颜色
sum=sum1; //回溯
}
}
if(find==0){ //已有的颜色都不能用
sum++; //总颜色数加一
color[i]=sum;
dfs(i+1); //求下一个点的颜色
}
}
}
int main(){
cin>>N;
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
cin>>G[i][j];
}
}
dfs(0);
cout<<"最少颜色数: "<<mins;
}