编写算法由依次输入的顶点数目_无向图顶点着色问题——回溯法

问题引入:

给定无向连通图G=(V,E)和正整数m,寻找最小的整数m,用m种颜色对G中的顶点着色,使得任意两个相邻顶点着色不同。

由于用m种颜色为无向图G=(V,E)着色,其中,V 的顶点个数为n,可以用一个n元组C=(c​1​​,c​2​​,⋯,cn​​) 来描述图的一种可能着色,其中,ci​​∈{1,2,⋯,m}(1⩽in) 表示赋予顶点i的颜色。例如,5元组(1,2,2,3,1)表示对具有5 个顶点的无向图的一种着色,顶点1着颜色1,顶点2着颜色2,顶点3 着颜色2,如此等等。par 如果在n元组C中,所有相邻顶点都不会着相同颜色,就称此n 元组为可行解,否则为无效解。

回溯法求解图着色问题,首先把所有顶点的颜色初始化为0,然后依次为每个顶点着色。在图着色问题的解空间树中,如果从根结点到当前结点对应一个部分解,也就是所有颜色指派都没有冲突,则在当前结点处选择第一棵子树继续搜索,也就是为下一个顶点着颜色1,否则,对当前子树的兄弟子树继续搜索,也就是为当前顶点着下一个颜色,如果所有m种颜色都已尝试过并且都发生冲突,则回溯到当前结点的父结点处,上一个顶点的颜色被改变,依此类推。下图是回溯法求解一个5阶图的解空间树。

bb049e345c1c8691ee9551e6fec63cf4.png

要求:运用回溯法策略编写一个能找出最少着色数,并能对图进行着色的函数。编写的程序必须对如下图中给出的各图能进行着色。

e07ac398a44b521088cd620d0e9f5e59.png

输入样例:

如下给出的输入样例中,第一行的两个数据分别是图的顶点数和边数,从第二行开始,每行3个数据,分别是两个关联顶点及其权值。输数据的总行数为输入的边数加1.

5 7
0 1 1
0 2 1
1 2 1
1 3 1
1 4 1
2 4 1
3 4 1

输出样例:

在输出样例中,[]前的数据为最小着色数,[]中的数分别是各顶点着色的颜色编号

3[1,2,3,3,1]

代码:

#include <stdio.h>
#include <stdlib.h>
#define INFINITY 255   //表示图中两个顶点无关联
typedef struct{
    int vertexNum; //图的顶点数
    int arcNum;    //图的边数
    int *arc;      //指向图中顶点的关联关系数组
    int *color;    //指向各顶点着色情况数组
}Graph;
void creatGraph(Graph *g);
int ColorGraph(Graph *g);
int Conflict(Graph *g,int k);
void dispVertexColor(Graph *g);
int main()
{
	Graph g;   //声明一个Graph类型的图g
	creatGraph(&g);//给图g定义顶点数、边数、生成顶点之间的关联关系
	int m=ColorGraph(&g);
	printf("%d",m);
	dispVertexColor(&g);
	return 0;
}
/**
 * 以下creatGraph()函数
 * 定义图的定点数、边数、
 * 图的邻接矩阵、顶点着色记录数组
 **/
void creatGraph(Graph *g)
{
    int x,y,k,w;
    scanf("%d %d",&g->vertexNum,&g->arcNum);
    g->arc=(int*)malloc(sizeof(int)*g->vertexNum*g->vertexNum);//创建邻接矩阵
    g->color=(int*)malloc(sizeof(int)*g->vertexNum);//创建顶点着色记录数组
    if(g->vertexNum==1&&g->arcNum==0)
    {
        g->arc[0]=0;
        g->color[0]=1;
        return;
    }
    for(x = 0;x < g->vertexNum;x++){//初始化邻接矩阵中的元素为INFINITY,即顶点之间不连通
        for(y = 0;y < g->vertexNum;y++)
            g->arc[g->vertexNum * x + y]=INFINITY;
        g->color[x]=0;//初始化着色记录数组元素为0,即无色。
    }
    for (k = 0; k < g->arcNum; k++){ //关联矩阵为一个对称矩阵
        scanf("%d %d %d",&x,&y,&w);
        g->arc[g->vertexNum*x+y]=w; //将关联边长度存入图的矩阵x行y列
        g->arc[g->vertexNum*y+x]=w; //将关联边长度存入图的矩阵y行x列
    }
}
void dispVertexColor(Graph *g)       //输出图g中各顶点的着色情况函数
{
    printf("[");
    for(int i = 0;i < g->vertexNum - 1; i++)
        printf("%d,",g->color[i]);
    printf("%d]n",g->color[g->vertexNum - 1]);
}

int ColorGraph(Graph *g)   //给图的顶点着色,函数返回值为最小着色数的值。
{
  int k=0,m=1;
  if(g->vertexNum==1 && g->arcNum==0)
  {
	  g->color[0]=1;
	  return m;
  }
  while(1)
  {
  while(k>=0)
  {
	  g->color[k]=g->color[k]+1;
	  while(g->color[k]<=m)
	  {
        if(Conflict(g,k)) break;
		else g->color[k]=g->color[k]+1;
	  } 
	  if(g->color[k]<=m && k==g->vertexNum-1)
		return m;
	  if(g->color[k]<=m && k<g->vertexNum-1)
	     k=k+1;
	  else
		  g->color[k--]=0;
  }
  k=0;
  m++;
  }
}
int Conflict(Graph *g,int k)   //检测顶点k与其邻接点着色是否冲突检,返回1为不冲突,返回0为冲突,此函数由ColorGraph()函数调用
{
	for(int i=0;i<k;i++)
 	{
		if(g->arc[g->vertexNum*k+i]!=255&&g->color[i]==g->color[k])
			return 0;
	}
	return 1;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值