第8节图论应用实例_图着色问题

  • 格式:doc
  • 大小:37.00 KB
  • 文档页数:7

下载文档原格式

  / 11
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

第8节图论应用实例_图着色问题

预备知识_回溯法

回溯法:在实际生活中,有些问题是不能用数学公式去解决的,它需要通过一个过程,此过程要经过若干个步骤才能完成,每一个步骤又分为若干种可能;同时,为了完成任务,还必须遵守一些规则,但这些规则无法用数学公式表示,对于这样一类问题,一般采用搜索的方法来解决,回溯法就是搜索算法(广度优先、深度优先等)中的一种控制策略,它能够解决许多搜索中问题。

回溯法基本思想:试探法,撞了南墙就回头。(一般采用深度优先搜索策略) 搜索策略:深度优先(不撞南墙不回头)。

在搜索过程中,如果求解失败,则返回搜索步骤中的上一点,去寻找新的路径,以求得答案。要返回搜索,前进中的某些状态必须保存,才能使得退回到某种状态后能继续向前。

白话搜索:如果用数组存放搜索信息,i表示数组下标(当前状态), ++i表示往前走(下一个状态),--i表示回溯(往回退,返回上一次状态)。

第8节图论应用实例_图着色(graph coloring)问题数学定义:给定一个无向图G=(V, E),其中V为顶点集合,E为边集合,图着色问题即为将V分为k个颜色组(k为颜色数),每个组形成一个独立集,即其中没有相邻的顶点。其优化版本是希望获得最小的k值。

典型应用:地图的着色、调度问题等。

k-着色判定问题:给定无向连通图G和k种不同的颜色。用这些颜色为图G的各顶点着色,每个顶点着一种颜色,是否有一种着色法使G中任意相邻的2个顶点着不同颜色,

例四色问题。设有如图1的地图,每个区域代表一个省,区域中的数字表示省的编号,现在要求给每个省涂上红、蓝、黄、白四种颜色之一,同时使相邻的省份以不同的颜色区分。

课外拓展:搜索“四色问题”,了解四色问题相关知识。

5

6

74

2

31

图1

问题分析:

(1)属于图的搜索问题。将问题简化:将每个省抽象为一个点,省之间的联系看为一条边,可以得到图2。

1

67

5

1

4

32

图2

(2)用邻接矩阵表示各省之间的相邻关系,二维数组实现:

1 表示省i与省j相邻, ,,ri,j,,0 表示省i与省j不相邻,

由图2可以得到如下矩阵:(对称矩阵)

1 2 3 4 5 6 7

1 0 1 0 0 0 0 1

2 1 0 1 1 1 1 1

3 0 1 0 1 0 0 0

4 0 1 1 0 1 0 0

5 0 1 0 1 0 1 0

6 0 1 0 0 1 0 1

7 1 1 0 0 0 1 0 为一对称矩阵。

(3)从编号为1的省开始按四种颜色顺序填色,当第1个省颜色与相邻省颜色不同时,就可以确定第1个省的颜色,然后,再依次对第2、第3,……,进行处理,直到所有省份颜色都涂上为止。 (4)问题关键在于填色过程中,如果即将填的颜色与相邻省的颜色相同,而且四种颜色都试探过,均不能满足要求,则需要回溯到上一个点(即前一个省),修改上一个省的颜色,重新试探下一个省的颜色。参考代码:(学生版本)

//回溯法:地图四色问题

// 大致思路:从第1个节点开始扫描,第1个节点颜色为1,第i个节点欲试探的颜色为color(color从1开始),

//循环判断i与已着色的前i-1个节点是否相邻,如果相邻且颜色也相同,那么颜色color则不合适,立刻跳出循环,

//下一个试探的颜色为++color,并且重新开始循环判断,试探下一个颜色是否合适。

2

//如果i与前i-1个节点循环判断后没有既相邻又同颜色的,那么第i个节点颜色为当前的color。

// 但是如果color到4都没有符合条件,那么我们就需要重新对i-1节点重新着色(回溯),它的颜色应该+1,并且继续循环判断i-1节点。

#include

#include

using namespace std;

const int MAX=100;

void mapcolor(int x[],int r[][MAX],int n);//x数组:各节点着色结果;r 数组:节点关系邻接矩阵;n:节点数 int main()

{

int r[MAX][MAX],x[MAX];

int n,i,j;

ifstream cin("map.txt");

cin>>n;

for(i=0;i

for(j=0;j

r[i][j]=-1;

for(i=0;i

for(j=0;j

cin>>r[i][j];

mapcolor(x,r,n);//节点着色

for(i=0;i

cout<<"color of node "<

return 0;

}

void mapcolor(int x[],int r[][MAX],int n) {

int i,color,j;//i:欲着色的当前节点,j:已着色的节点

x[0]=1;//第1个节点颜色为1

i=1;//节点计数

color=1;//颜色,从1开始

while(i

while(color<=4 && i

{

for(j = 0; j

if(r[i][j] == 1 && x[j] ==color) //相邻节点,且颜色相同,则跳出循环break;

}

if(j < i)

++color;//下一个欲试探的颜色

else

3

{

x[i]=color;//欲着的颜色和前i-1个已着色的节点不冲突,当前节点着色为color颜色

++i;//准备试探下一个节点

color=1;//颜色重新赋值