图的着色问题

问题起源于一个宣讲会时间安排问题,有若干个部门要进行宣讲会,有若干个同学对多个部门有兴趣,希望在给出一个时间方案,要求所有的同学都可以参加所有他感兴趣的宣讲会,同时要求在最短的时间内把宣讲会结束。

把每个宣讲会作为一个点,每个同学感兴趣的宣讲会两两相连,就变成了一个图的最少着色问题。

图的m-着色判定问题——给定无向连通图Gm种不同的颜色。用这些颜色为图G的各顶点着色,每个顶点着一种颜色,是否有一种着色法使G中任意相邻的2个顶点着不同颜色?

图的m-着色优化问题——若一个图最少需要m种颜色才能使图中任意相邻的2个顶点着不同颜色,则称这个数m为该图的色数。求一个图的最小色数m的问题称为m-着色优化问题。

 

算法描述(迭代算法)

 

 color[n]存储n个顶点的着色方案,可以选择的颜色为1m

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");
        }
    }
}

 

posted on 2013-07-12 17:20  Stomach_ache  阅读(1191)  评论(0编辑  收藏  举报

导航