图的m着色问题

  图的m-着色问题:给定无向连通图G和m种颜色。用这些颜色为G的各个顶点着色,每个顶点着一种颜色。如果有一种色法使G的每条边的两个顶点着不同的颜色,则称这个图示m个着色的。图的m着色问题是对于给定图G和m种颜色,找出所有的不同的着色方法。

  假设图G有6个顶点,可以用三种颜色来着色,三种颜色的编号分别是1,2,3.


下面是无向图G的一种涂色情况,根据定义可得相邻的两点的颜色不能是一样的,但是并没有要求一个点的两段的结点也要求是一样的。所以这是一个简单的回溯问题。

创建一个包含6个结点的图,其中其结点分别为1,2,3,4,5,6,将其存放在数据d[20]中(d[]={1,2,3,4,5,6});然后创建一个数据color[20]保存对应的结点的涂色情况。数值1,2,3分别代表上图的颜色。

着色的过程

(1)首先将第一个节点图上1号颜色

(2)然后判断2号结点的邻结点涂了哪些颜色,在剩余颜色中选择一种没有被图的颜色。

(3)按照结点存储的顺序(即1,2,3,4,5,6)的顺序一次将结点进行涂色就得到了上面的图

回溯探索其他的可能性(6,5,4,3,2,1逆向回溯探索)

(4)将结点6选择3号颜色,输出结果。然后将结点6置为未着色。

(5)然后将5号结点选择其他的颜色(由上图可知5号不能换成不能换成其他颜色,只能4号换了,然后再换5号),在重新选择6号结点的颜色。

(6)依次是4,3,2,1,选择与之前不同的颜色,然后又从后往前重新探索。

如图所示


4号换了一种颜色之后的,5号只剩一个选择,而6号又能有两种选择。

第一种


第二种

简单的说就是从前往后遍历着色,然后再向前回溯之后,再往后遍历着色。

那么什么时候完结呢?

当1号结点着色完三种情况,并且将所有的结点,然后有探索到6号结点。

这个问题得关键其实是遍历的顺序,就是按照在数组中存放的顺序来进行遍历,开始按照dfs的方法进行的遍历,结果出现了一些不可控的问题,调试许久不能的到想要的结果。

#include <iostream>

using namespace std;

int a[20][20]={0};
int d[20];//节点
int n,s,m;
int color[20]={0};
int sum=0;
int num=1;
int flag;

int First(int t)
{
    for(int i = 0; i < n; i++)
        if(a[t][i] != 0)
        {
            return i;
        }

    return -1;//无邻结点
}

int Next(int w,int v)
{
    for(int i = v + 1; i < n; i++)
        if(a[w][i])
        {
            return i;
        }

    return -1;
}

int Locate(int v)
{
    for(int i=0;i<n;i++)
        if(d[i]==v)
            return i;

    return -1;
}

int Check(int i)
{
    for(int t=First(i);t != -1;t=Next(i,t))
        if(color[i]==color[t]&&a[i][t])
            if(color[i]&&color[t])//两个已经涂色
                return 0;

    return 1;
}

void Print()
{
	sum++;
	for(int i=0;i<n;i++)
		printf("%-3d",color[i]);
	printf("\n");
}

void Color(int i)
{
	if(i==n)
	{
		Print();
	}
	else
	{
		for(int t=1;t<=m;t++)
		{
			color[i]=t;
			flag=Check(i);
			if(flag)
			{
				Color(i+1);
			}
		}
		color[i]=0;//回溯
	}
}

int main()
{
    int p,q,num=0;
    scanf("%d%d%d",&n,&s,&m);

    for(int i=0;i<n;i++)
        scanf("%d",&d[i]);

    for(int i=0;i<s;i++)
    {
        scanf("%d%d",&p,&q);
        a[Locate(p)][Locate(q)]=1;
		a[Locate(q)][Locate(p)]=1;
    }

	Color(0);
    printf("一共有%d种涂色方案\n",sum);
    return 0;
}







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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值