c解决图的涂色问题

来源:互联网 发布:军方网络 编辑:程序博客网 时间:2024/05/16 08:19

问题描述:

给出5个顶点的无向连通图的四着色问题。

思路:和八皇后问题雷同,用回溯法逐步试探。先给任一个节点涂色,然后为相邻节点涂色,涂色时逐步试探使得不撞色。


代码如下:


#include <stdio.h>void  visit(int g[],int n);int canDraw(int c[][6],int n, int g[], int k){int i = 1,flag = 1;//flag初始值为0的话,如果k=1,即给第一个节点涂色,下面的for循环都不满足,直接返回flag,为假,这就错了。 for(; i < k; i++)//涂第k个节点时,只要前k-1个已经涂好的节点如果有与这个节点相连颜色不同即可 {if(c[i][k]){if(g[i] != g[k])          flag++;else{ flag = 0; break;    }    }}return flag;} int drawColor(int c[][6], int n, int g[]){int k = 2,find = 0,count = 0, m = 4;g[1] = 1;//红橙黄绿用1234表示。初始节点(用1表示)涂红色。 find = 1; while(k >= 1)//当k回退到k=0,跳出循环。如果k>=0,则最后一次回退k=0,又从g[0]=1开始,从第一个节点(k=1)开始涂色有48,回退一次回到 g[0]=2,从第一个节点开始涂色也有48,直到g[0] =5跳出循环,执行回退k=-1 退出程序,如图一所示 {printf("\nwhile");find = 0;//while((find == 0) && (g[k] < 5))//为当前节点k找一个合适颜色,或者设标志位跳出循环,或者如下方式设立break while((g[k] < 5)) //须有跳出while的break设置 {g[k]++;printf("*whilewhile g[%d]=%d ",k,g[k]);if(canDraw(c,n,g,k)&& (g[k] < 5))//“&& (g[k] < 5)”非常重要。否则g[k]等于5时,会漏掉。见图二和图三。 {find = 1; break;//跳出循环 }}if(find == 1)//当前节点k可以涂色,继续涂下一个节点 {if(k == (n-1))//数组长度为n=6,但是节点数为5。 {printf("##final graph coloring: ");visit(g,k);//return 1;//如果只要给出第一种涂色方案,那么直接返回程序就行。要统计所有涂色方案则程序继续执行,一直执行外层的while循环,直到第一个节点试完最后一种颜色,其他节点也没有别的颜色可搭配了为止(此时k=0),程序结束。 count++;}else{k++;printf("##next k=%d",k);}}else //当前节点k涂所有颜色终和相邻节点撞色,没法继续涂色,前面一个节点k-1必须换颜色重新涂 {g[k] = 0;k--; printf("*elsebacktrace k=%d",k);}}printf("\nways of drawing graph:count= %d",count);}void  visit(int g[],int n)//输出涂色方案 { int i;for(i = 1 ; i<= n; i++){printf("%2d",g[i]);}}int main(){int i,g[6] = {0},c[6][6]={{0,0,0,0,0,0},  {0,0,1,1,1,0},  {0,1,0,1,1,1},  {0,1,1,0,1,0},  {0,1,1,1,0,1},  {0,0,1,0,1,0}};//图的邻接矩阵,表示5个节点邻接关系。设长度为6是因为数组从下标为1开始。 drawColor(c,6, g);return 1; }


代码中的图如下所示;

                         图一

这个图表示,求给出所有涂色方案时,外层while跳出循环的k取值。当k>=0时,出错情况。

                    图二


                              图三

图二表示,漏掉判断条件“&& (g[k] < 5)”出错情况,作为对比给出图三的正确情况。


0 0
原创粉丝点击