图着色问题 (转)

转自:
此处为了尊重作者,不更改他人的文章!后续自己将分析。
以下为:chhaya 的内容。
图的m着色问题:
   给定无量连通图g和m种颜色,用这些颜色为图g的各个顶点着色,每个顶点着一种,是否有一种着色法使图中每条边的两个顶点着有不同的颜色。
 
算法设计:
   给定图g(v,e)和m种颜色,如果这个图不是m可着色,给出否定回答,是的话找出所有不同着色法。
分析:
   用邻接矩阵表示图g,如果顶点i跟j之间有边,则g[i][j] = 1,否则g[i][j] = 0.用整数1,2,...,m表示m种颜色,顶点i的颜色用x[i]表示,所以x[1:n]是一种着色方案。
   在算法traceback中,当i>n时,就是所有顶点都上了色,得到新的m着色方案,当前m着色方案总数sum增一,输出方案。
   当i<n时,就是未着色完所有顶点,当前顶点i有x[i] = 1, 2....m种颜色可图,对于每种颜色由函数ok判断可行性,并用dfs对可行颜色搜索,或减去不可行方案。

代码如下:
 

#include <stdio.h>
#include <conio.h>
#define N 20

int n, sum = 0, m;
int x[N+1];
int g[N+1][N+1];

int ok(int t)
{
    for(int j = 1; j<=n; j++)
        if(!= j)
        {
            if(g[t][j] == 1 && x[t] == x[j])
                return 0;
        }
    return 1;
}
void back_track(int t)
{
    int i;
    if(> n)
    {
        sum++;
        for(i=1; i<=n; i++)
            printf("%d ", x[i]);
        printf("\n");
    }
    else
    {
        for(int i = 1; i <= m; i++)
        {
            x[t] = i;
            if(ok(t)) 
                back_track(t+1);
            x[t] = 0;
        }
    }
}

int main()
{
    int k, i, j;

    freopen("in.txt", "r", stdin);
    scanf("%d%d", &n, &m); //n个顶点,m种颜色

    for(i=1; i<=n; i++)
        for(j=1; j<=n; j++)
        {
            scanf("%d", &g[i][j]); 
            g[j][i] = g[i][j];
        }
    back_track(1);
    printf("sum :%d\n", sum);
    getch();
    return 0;
}

input:

4 4
0 1 1 0
1 0 1 1
1 1 0 1
0 1 1 0

output:

1 2 3 1
1 2 3 4
1 2 4 1
....... //太多了,省略输出几种
4 3 2 1
4 3 2 4
sum :48

----------------------------------------

最近重新学习搜索,dfs喜欢用非递归的, 补充在后面吧;

这是poj1129

#include <stdio.h>
#include <string.h>
#define N 27
int g[N][N]
int c[N];  //放每个点的颜色
char *is[5] = {" ", "channel", "channels", "channels", "channels"};

int isok(int x, int k)
{
    int i;
    for(i=0; i<k; i++)
    {
        if(g[i][k] && c[i] == x)
            return 0;
    }
    return 1;
}

int solve(int n, int m)
{
    int k;
    memset(c, 0, sizeof(c));
    k = 0;
    c[k] = 0;
    while(>= 0)
    {
        c[k]++;
        for(; c[k]<=m; c[k]++)
        {
            if(isok(c[k], k))
                break;
        }
        if(c[k] <= m)
        {
            if(== n-1)
                return 1;
            else
                k++;
        }
        else
        {
            c[k] = 0;
            k--;
        }
    }
    return 0;
}

int main()
{
    int n, i;
    char a, c;
    freopen("1129.in", "r", stdin);
    while(scanf("%d", &n), n)
    {
        memset(g, 0, sizeof(g));
        for(i=0; i<n; i++)
        {
            scanf(" %c:", &a);
            while(scanf("%c", &c), c!='\n')
            {
                g[a-'A'][c-'A'] = 1;
            }
        }
        for(i=1; i<5; i++)
            if(solve(n, i))
            {
                printf("%d %s needed.\n", i, is[i]);
                break;
            }    
    }
    return 0;
}


以下为: 快乐的霖霖  的内容。

图着色算法简介

        图的 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与所有其它相邻顶点无颜色冲突,则继续为下一顶点着色;否则,回溯,测试下一颜色。

代码如下:

  1. #include<stdio.h>  
  2.   
  3. int color[100];  
  4. bool ok(int k,int c[][100]) //判断顶点k的着色是否发生冲突  
  5. {  
  6.   int i,j;  
  7.   for(i=1;i<k;i++)  
  8.   {  
  9.     if(c[k][i]==1&&color[i]==color[k])  
  10.         return false;  
  11.   }  
  12.   return true;  
  13. }  
  14.   
  15. void graphcolor(int n,int m,int c[][100])  
  16. {  
  17.   int i,k;  
  18.   for(i=1;i<=n;i++)  
  19.       color[i]=0;  
  20.   k=1;  
  21.   while(k>=1)  
  22.   {  
  23.    color[k]=color[k]+1;  
  24.    while(color[k]<=m)  
  25.        if(ok(k,c)) break;  
  26.        else color[k]=color[k]+1; //搜索下一个颜色  
  27.    if(color[k]<=m&&k==n)  
  28.    {  
  29.      for(i=1;i<=n;i++)  
  30.          printf("%d ",color[i]);  
  31.      printf("\n");  
  32.    }  
  33.    else if(color[k]<=m&&k<n)  
  34.        k=k+1; //处理下一个顶点  
  35.    else  
  36.    {  
  37.      color[k]=0;  
  38.      k=k-1;//回溯  
  39.    }  
  40.   }  
  41. }  
  42. void main()  
  43. {  
  44.   int i,j,n,m;  
  45.   int c[100][100];//存储n个顶点的无向图的数组  
  46.   printf("输入顶点数n和着色数m:\n");  
  47.   scanf("%d %d",&n,&m);  
  48.   printf("输入无向图的邻接矩阵: \n");  
  49.   for(i=1;i<=n;i++)  
  50.       for(j=1;j<=n;j++)  
  51.           scanf("%d",&c[i][j]);  
  52.   printf("着色所有可能的解:\n");  
  53.   graphcolor(n,m,c);  
  54. }  

以下为:码农SW 的内容。

m图着色问题:

题目大意:

1,已知一个图g和m>0种颜色,在只准使用这m种颜色对g的结点着色的情况下,是否能使图中任何相邻的两个结点都具有不同的颜色呢?这个问题称为m-着色判定问题

2,在m-着色最优化问题则是求可对图g着色的最小整数m。这个整数称为图g的色数。这是求图的最少着色问题,求出m的值。

题目的解法:

第一个问题,m-着色判定问题:

可以通过回溯的方法,不断的为每一个节点着色,在前面n-1个节点都合法的着色之后,开始对第n个节点进行着色,这时候枚举可用的m个颜色,通过和第n个节点相邻的节点的颜色,来判断这个颜色是否合法,如果找到那么一种颜色使得第n个节点能够着色,那么说明m种颜色的方案是可行的。返回真即可:

[cpp]  view plain copy
  1. //用于判断当前节点上涂上这个颜色可不可行,与其邻接节点的颜色做判断,这里用邻接表来存储图的信息  
  2. bool isok(int step)  
  3. {  
  4.      vector<int>::iterator iter;  
  5.      for(iter = input[step].begin(); iter != input[step].end(); iter++)  
  6.      {  
  7.               if(Color[step] == Color[*iter]) return false;  
  8.      }  
  9.      return true;  
  10. }  
  11. //step表示0->n的节点,color_num是指给color_num的颜色的个数可用  
  12. //判断如果给color_num的颜色的个数是否可行,如果可行返回true,否则false   
  13. bool DFS(int step, int color_num)  
  14. {  
  15.      if(step >= n) return true;  
  16.      else  
  17.      {  
  18.          int i;  
  19.          for(i = 1; i<= color_num; i++)  
  20.          {  
  21.                Color[step] = i;  
  22.                if(isok(step))  
  23.                {  
  24.                      if(DFS(step + 1, color_num))  
  25.                           return true;  
  26.                }  
  27.                Color[step] = 0;  
  28.          }  
  29.      }  
  30.      return false;  
  31. }  

第二个问题:求出最少的着色数m

有了上面的问题的积累,对于这个问题就很简单了,只要从1到n枚举颜色数,来调用上面的DFS(0, m),如果有一次调用返回true,那么这时这个颜色就是我们要求的最少的着色数。

[cpp]  view plain copy
  1. for(i = 1; i<= n; i++)  
  2. {  
  3.       if(DFS(0, i))  
  4.       {  
  5.              cout << "the min colors :" << i << endl;  
  6.              break;  
  7.       }  
  8. }  


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值