c解决图的涂色问题

问题描述:

给出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; 
}

代码中的图如下所示;

《c解决图的涂色问题》

                         图一

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

《c解决图的涂色问题》

                    图二

《c解决图的涂色问题》

                              图三

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

    原文作者:骑士周游问题
    原文地址: https://blog.csdn.net/u012270113/article/details/25828363
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞