问题起源于一个宣讲会时间安排问题,有若干个部门要进行宣讲会,有若干个同学对多个部门有兴趣,希望在给出一个时间方案,要求所有的同学都可以参加所有他感兴趣的宣讲会,同时要求在最短的时间内把宣讲会结束。
把每个宣讲会作为一个点,每个同学感兴趣的宣讲会两两相连,就变成了一个图的最少着色问题。
图的m-着色判定问题——给定无向连通图G和m种不同的颜色。用这些颜色为图G的各顶点着色,每个顶点着一种颜色,是否有一种着色法使G中任意相邻的2个顶点着不同颜色?
图的m-着色优化问题——若一个图最少需要m种颜色才能使图中任意相邻的2个顶点着不同颜色,则称这个数m为该图的色数。求一个图的最小色数m的问题称为m-着色优化问题。
算法描述(迭代算法)
color[n]存储n个顶点的着色方案,可以选择的颜色为1到m
t=1
对当前第t个顶点开始着色:
若t>n 则已求得一个解,输出着色方案即可
否则,依次对顶点t着色1-m,
若t与所有其它相邻顶点无颜色冲突,则继续为下一顶点着色;否则,回溯,测试下一颜色。
hdu 2208
/*程序效率太低,不懂怎么改进。。。。。*/
#include<stdio.h>
#include<string.h>
#define max 15
bool map[max][max];//存图的临接矩阵
//bool vis[max];//记录该节点是否已经着色
int color[max];//记录每个节点的颜色
int n,m;//n为节点个数,m为最大着色数
bool flag;
bool OK(int k){
for(int i=1;i<k;i++){
if(map[k][i]==1&&color[i]==color[k]){
return false;
}
}
return true;
}
void solve(int cnt){
if(cnt==n){
/*for(int i=1;i<=n;i++){
printf("%d: %d\n",i,color[i]);
}*/
flag=true;
}
else for(int k=1;k<=m;k++){
int next=cnt+1;
color[next]=k;
if(OK(next)){
solve(cnt+1);
if(flag){
return;
}
}
}
}
int main(){
while(~scanf("%d%d",&n,&m)){
int i,j,k,a;
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
map[i][j]=true;
}
}
memset(color,0,sizeof(color));
for(i=1;i<=n;i++){
scanf("%d",&k);
for(j=1;j<=k;j++){
scanf("%d",&a);
map[i][a+1]=false;
map[a+1][i]=false;
}
}
flag=false;
solve(0);
if(flag){
puts("YES");
}
else{
puts("NO");
}
}
}