第8节图论应用实例_图着色问题
- 格式:doc
- 大小:37.00 KB
- 文档页数:7
第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;//颜色重新赋值