|
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
|
图着色算法简介
图的m-着色优化问题——若一个图最少需要m种颜色才能使图中任意相邻的2个顶点着不同颜色,则称这个数m为该图的色数。求一个图的最小色数m的问题称为m-着色优化问题。
算法实现
算法描述:color[n]存储n个顶点的着色方案,可以选择的颜色为1到m。当t=1时,对当前第t个顶点开始着色:若t>n,则已求得一个解,输出着色方案即可。否则,依次对顶点t着色1-m, 若t与所有其它相邻顶点无颜色冲突,则继续为下一顶点着色;否则,回溯,测试下一颜色。
代码如下:
- #include<stdio.h>
-
- int color[100];
- bool ok(int k,int c[][100]) //判断顶点k的着色是否发生冲突
- {
- int i,j;
- for(i=1;i<k;i++)
- {
- if(c[k][i]==1&&color[i]==color[k])
- return false;
- }
- return true;
- }
-
- void graphcolor(int n,int m,int c[][100])
- {
- int i,k;
- for(i=1;i<=n;i++)
- color[i]=0;
- k=1;
- while(k>=1)
- {
- color[k]=color[k]+1;
- while(color[k]<=m)
- if(ok(k,c)) break;
- else color[k]=color[k]+1; //搜索下一个颜色
- if(color[k]<=m&&k==n)
- {
- for(i=1;i<=n;i++)
- printf("%d ",color[i]);
- printf("\n");
- }
- else if(color[k]<=m&&k<n)
- k=k+1; //处理下一个顶点
- else
- {
- color[k]=0;
- k=k-1;//回溯
- }
- }
- }
- void main()
- {
- int i,j,n,m;
- int c[100][100];//存储n个顶点的无向图的数组
- printf("输入顶点数n和着色数m:\n");
- scanf("%d %d",&n,&m);
- printf("输入无向图的邻接矩阵: \n");
- for(i=1;i<=n;i++)
- for(j=1;j<=n;j++)
- scanf("%d",&c[i][j]);
- printf("着色所有可能的解:\n");
- graphcolor(n,m,c);
- }
- #include<stdio.h>
- int color[100];
- bool ok(int k,int c[][100]) //判断顶点k的着色是否发生冲突
- {
- int i,j;
- for(i=1;i<k;i++)
- {
- if(c[k][i]==1&&color[i]==color[k])
- return false;
- }
- return true;
- }
- void graphcolor(int n,int m,int c[][100])
- {
- int i,k;
- for(i=1;i<=n;i++)
- color[i]=0;
- k=1;
- while(k>=1)
- {
- color[k]=color[k]+1;
- while(color[k]<=m)
- if(ok(k,c)) break;
- else color[k]=color[k]+1; //搜索下一个颜色
- if(color[k]<=m&&k==n)
- {
- for(i=1;i<=n;i++)
- printf("%d ",color[i]);
- printf("\n");
- }
- else if(color[k]<=m&&k<n)
- k=k+1; //处理下一个顶点
- else
- {
- color[k]=0;
- k=k-1;//回溯
- }
- }
- }
- void main()
- {
- int i,j,n,m;
- int c[100][100];//存储n个顶点的无向图的数组
- printf("输入顶点数n和着色数m:\n");
- scanf("%d %d",&n,&m);
- printf("输入无向图的邻接矩阵: \n");
- for(i=1;i<=n;i++)
- for(j=1;j<=n;j++)
- scanf("%d",&c[i][j]);
- printf("着色所有可能的解:\n");
- graphcolor(n,m,c);
- }
m图着色问题:
题目大意:
1,已知一个图g和m>0种颜色,在只准使用这m种颜色对g的结点着色的情况下,是否能使图中任何相邻的两个结点都具有不同的颜色呢?这个问题称为m-着色判定问题。
2,在m-着色最优化问题则是求可对图g着色的最小整数m。这个整数称为图g的色数。这是求图的最少着色问题,求出m的值。
题目的解法:
第一个问题,m-着色判定问题:
可以通过回溯的方法,不断的为每一个节点着色,在前面n-1个节点都合法的着色之后,开始对第n个节点进行着色,这时候枚举可用的m个颜色,通过和第n个节点相邻的节点的颜色,来判断这个颜色是否合法,如果找到那么一种颜色使得第n个节点能够着色,那么说明m种颜色的方案是可行的。返回真即可:
- //用于判断当前节点上涂上这个颜色可不可行,与其邻接节点的颜色做判断,这里用邻接表来存储图的信息
- bool isok(int step)
- {
- vector<int>::iterator iter;
- for(iter = input[step].begin(); iter != input[step].end(); iter++)
- {
- if(Color[step] == Color[*iter]) return false;
- }
- return true;
- }
- //step表示0->n的节点,color_num是指给color_num的颜色的个数可用
- //判断如果给color_num的颜色的个数是否可行,如果可行返回true,否则false
- bool DFS(int step, int color_num)
- {
- if(step >= n) return true;
- else
- {
- int i;
- for(i = 1; i<= color_num; i++)
- {
- Color[step] = i;
- if(isok(step))
- {
- if(DFS(step + 1, color_num))
- return true;
- }
- Color[step] = 0;
- }
- }
- return false;
- }
第二个问题:求出最少的着色数m
有了上面的问题的积累,对于这个问题就很简单了,只要从1到n枚举颜色数,来调用上面的DFS(0, m),如果有一次调用返回true,那么这时这个颜色就是我们要求的最少的着色数。
- for(i = 1; i<= n; i++)
- {
- if(DFS(0, i))
- {
- cout << "the min colors :" << i << endl;
- break;
- }
- }