第8节图论应用实例_图着色问题
图的着色问题--C++实现(含详细注释)

图的着色问题一、题目简述(1) 图的m-着色判定问题给定一个无向连通图 G 和 m 种不同的颜色。
用这些颜色为图 G 的各顶点着色,每个顶点着一种颜色,是否有一种着色法使 G 中任意相邻的两个顶点着不同颜色?(2) 图的m-着色优化问题若一个图最少需要 m 种颜色才能使图中任意相邻的两个顶点着不同颜色,则称这个数 m 为该图的色数。
求一个图的最小色数 m 的问题称为m-着色优化问题。
二、算法思想1. m-着色判定问题总体思想:通过回溯的方法,不断为每一个节点着色,每个点的颜色由一个数字代表,初始值为1。
在对前面 step - 1 个节点都合法的着色之后,开始对第 step 个节点进行着色。
如果 n 个点均合法,且颜色数没有达到 m 种,则代表存在一种着色法使 G中任意相邻的两个顶点着不同颜色。
具体步骤:1. 对每个点 step ,有 m 种着色可能性,初始颜色值为1。
2. 检查第 step 个节点颜色的可行性,若与某个已着色的点相连且颜色相同,则不选择这种着色方案,并让颜色值加1,继续检查该点下一种颜色的可行性。
3. 如果第 step 点颜色值小于等于 m ,且未到达最后一个点,则进行对第 step + 1 点的判断。
4. 如果第 step 点颜色值大于 m ,代表该点找不到合适的分配方法。
此时算法进行回溯,首先令第 step 节点的颜色值为0,并对第 step - 1 个点的颜色值+1后重新判断。
5. 如果找到一种颜色使得第 step 个节点能够着色,说明 m 种颜色的方案是可行的。
6. 重复步骤2至5,如果最终 step 为0则代表无解。
2. m-着色优化问题基于问题1,对于一个无向图 G ,从1开始枚举染色数,上限为顶点数,第一个满足条件的颜色数即为所求解。
三、实现过程(附代码)1. m-着色判定问题#include<iostream>using namespace std;int color[100]; // 每个点的颜色int mp[100][100]; // 图的邻接矩阵int n, m, x; // n顶点,m种颜色方案,x条边bool check(int step) {// 判断与step点相邻的点,颜色是否与step点相同,若相同则返回falsefor (int i=1; i<=n; i++) {if (mp[step][i] ==1&&color[i] ==color[step]) {return false;}}return true;}bool Solve(int m) {// 求解是否可以找到一种可行的染色方案int step=1; // step指示当前节点while (step>=1) {color[step] +=1; // 假定颜色值从1开始,若为回溯,选择下一种方案while (color[step] <=m) { // 按照问题条件选择第step点颜色if (check(step)) {break;} else {color[step]++; // 搜索下一个颜色}}if (color[step] <=m&&step==n) { // 如果找完n个点,且染色方法小于等于m种 return true;} else if (color[step] <=m&&step<n) {step++; // 求解下一个顶点} else { // 如果染色数大于m个,回溯color[step] =0; // 回溯,该点找不到合适的分配方法,对上一点进行分析step--;}}// 如果step退到0,则代表无解return false;}int main() {int i, j;bool ans=false;cout<<"输入顶点数n和着色数m"<<endl;cin>>n>>m;cout<<"输入边数"<<endl;cin>>x;cout<<"具体输入每条边"<<endl;for (int p=0; p<x; p++) { // 以无向邻接矩阵存储边cin>>i>>j;mp[i][j] =1;mp[j][i] =1;}if (Solve(m)) {cout<<"有解";} else {cout<<"无解";}return0;}2. m-着色优化问题#include<iostream>using namespace std;int color[100]; // 每个点的颜色int mp[100][100]; // 图的邻接矩阵int n, m, x; // n顶点,m种颜色方案,x条边bool check(int step) {// 判断与step点相邻的点,颜色是否与step点相同,若相同则返回falsefor (int i=1; i<=n; i++) {if (mp[step][i] ==1&&color[i] ==color[step]) {return false;}}return true;}bool Solve(int m) {// 求解是否可以找到一种可行的染色方案int step=1; // step指示当前节点while (step>=1) {color[step] +=1; // 假定颜色值从1开始,若为回溯,选择下一种方案while (color[step] <=m) { // 按照问题条件选择第step点颜色if (check(step)) {break;} else {color[step]++; // 搜索下一个颜色}}if (color[step] <=m&&step==n) { // 如果找完n个点,且染色方法小于等于m种 return true;} else if (color[step] <=m&&step<n) {step++; // 求解下一个顶点} else { // 如果染色数大于m个,回溯color[step] =0; // 回溯,该点找不到合适的分配方法,对上一点进行分析step--;}}// 如果step退到0,则代表无解return false;}int main() {int i, j;bool ans=false;cout<<"输入顶点数n"<<endl;cin>>n;cout<<"输入边数"<<endl;cin>>x;cout<<"具体输入每条边"<<endl;for (int p=0; p<x; p++) { // 以无向图邻接矩阵存储边 cin>>i>>j;mp[i][j] =1;mp[j][i] =1;}for (m=1; m<=n; m++) { // 从小到大枚举着色数mif (Solve(m)) { // 如果有解,输出答案并跳出循环cout<<"最小色数m为 "<<m;break;}}return0;}四、结果及分析问题1测试用例:问题2测试用例:经检验,最少着色数的范围为2-4,意味着使 G 中任意相邻的两个顶点着不同颜色最多需要4种颜色。
图论中的平面图与染色问题

图论中的平面图与染色问题图论是数学的一个分支,研究的是图的性质和图之间的关系。
在图论中,平面图与染色问题是重要的研究方向。
一、平面图平面图是指可以在平面上画出的图,其中任意两条边都不相交,任意两个顶点之间都只有一条边相连。
平面图可以用来描述许多实际问题,如地图、电路等。
在平面图中,有一个重要的定理,即欧拉定理。
欧拉定理是数学家欧拉在1736年提出并证明的,它给出了平面图中顶点数、边数和面数的关系。
根据欧拉定理,对于连通的平面图,满足公式:V - E + F = 2,其中V表示顶点数,E表示边数,F表示面数。
二、染色问题染色问题是图论中的一个经典问题,即给定一个图,如何用有限种颜色对图的各个顶点进行染色,使得相邻的顶点之间的颜色不相同。
这是一种常见的应用问题,如地图着色、课程表安排等。
在染色问题中,有一个重要的定理,即四色定理。
四色定理是染色问题中的一个著名定理,它指出任何平面图都可以用至多四种颜色对其顶点进行染色,使得相邻的顶点颜色不同。
三、平面图与染色问题的关系平面图与染色问题之间有着紧密的联系。
通过合理的染色方案,可以将一个平面图的顶点进行染色,满足相邻顶点颜色不同的要求。
同时,染色问题的解法与平面图的结构和性质也有关系。
在研究平面图与染色问题时,可以通过绘制平面图的平面嵌入图来分析和求解染色问题。
平面嵌入图是平面图在平面上的一种表示形式,可以把平面图的顶点和边绘制在平面上,形成一种更加直观的图形。
在解决染色问题时,可以借助平面嵌入图的结构和特性,通过一定的算法进行染色。
例如,可以利用贪心算法对顶点进行依次染色,确保相邻顶点染不同的颜色。
四、应用举例平面图与染色问题在实际中有广泛的应用。
一个典型的例子是地图着色问题。
在地图上,每个国家或地区可以用一个顶点表示,国家或地区之间的边表示它们的相邻关系。
通过对地图进行染色,可以实现相邻国家或地区的颜色不同,从而更加方便地辨认。
另一个例子是课程表安排问题。
实验四 回溯法(图着色问题)

01 234 001 1 01 1 1 01 01 21 1 01 0 3001 01 41 1 01 0
class MGraph { public:
MGraph(int v,int s); void mColoring(int m,int *x); //一维数组x,存放1~n个顶点的颜色 ~MGraph(); private: void NextValue(int k,int m,int *x); void mColoring (int k,int m,int *x); int **a; //二维数组a,存储图的邻接矩阵 int n,e; //n表示图的顶点数,e表示边数 };
无向图G
【实验内容与要求】
图的着色问题:设G=(V,E)是一连通无向图,有3 种颜色,用这些颜色为G的各顶点着色,每个顶点着 一种颜色,且相邻顶点颜色不同。试用回溯法设计一 个算法,找出所有可能满足上述条件的着色法。
无向图G
无向图G
对应这个无向图的状态空间树应该是怎样的?
是一个完全3叉树,共6层
实验四 回溯法 — 图的着色问题
图的着色问题是由地图的着色问题引申而来的: 用m种颜色为地图着色,使得地图上的每一个 区域着一种颜色,且相邻区域颜色不同。
问题处理:如果把每一个区域收缩为一个顶点, 把相邻两个区域用一条边相连接,就可以把一
个区域图抽象为一个平面图。
地图(map)中地区的相邻关系,在图(graph )中用边表示。
//若(i, j)是图的边,且相邻结点k和j颜色相同 //发生冲突,选下一种颜色
if (j==k) return; //成功选择一种颜色返回 }while (1); //循环尝试颜色 }
运行结果:
图着色问题

ac b ed c g e bgd b ed f b ec f df
故G的极小覆盖为 { a , c , e , g } { b , c , , d , e , g } { b , d , , e ,f } { b , c , , d ,f } 取• 其S补te集p2,:得求到出G一的切所若有干极极大大独独立立集集:和所{ 有b ,顶d ,点f} 的{ a 子,,f 集} { a ,, c ,g } { a ,, e ,g }
回溯法
14
回溯法
step two:以颜色1为顶点B着色生成结点3时,产生 (1,1,0,0,0),是个无效着色,结点3为d_结点。
Step three:以颜色2为顶点B着色生成结点4,产 生(1,2,0,0,0),是个有效着色。
Step four:分别以颜色1和2为顶点C着色生成结点 5和6,产生(1,2,1,0,0)和(1,2,2,0,0),都是无效着 色,因此结点5和6都是d_结点。
9
穷举法-Welch Powell着色法
• 给定图G,用Welch Powell法对图G着
色1
A2 3
2
A3
1
A4
A5
A6 3
10
穷举法-Welch Powell着色法
• 第一步:将图G中的结点按度数的递减顺序排
列: A 5,A 3,A 7,A 1,A 2,A 4,A 6,A 8
• 第二步:用第一种颜色对A5着第一种颜色, 并对与A5不邻接的结点A1也着第一种颜色。
//搜索下一个颜色
•
if (color[k]<=m && k= =n)
//求解完毕,输出解
•
{ for (i=1; i<=n; i++)
着色问题分析

记号 c(v) = 边着色C表现于v的不同颜色数。 易见, c(v) d(v) vV。 C为正常边着色 c(v) = d(v) vV。
称G的k-边着色C’ 为其k-边着色C的一个改进 c' (v) c(v) 。
C为最优k-边着色(optimal k-edge colouring) C不能再改进 。
∴
c' (v) c(v)
v V v V
,
这与C为最优矛盾。
图论及其应用
5
6.1 边色数
定理6.1 设G为偶图,则 = 。 证明: (Wilson)对 进行归纳。当 = 1 时显然成立。假设
对 < k( 2) 都成立,而 (G)= k 。任取G的一边 e = uv , 考虑 G’ = G - e 。
图论及其应用
7
6.1 Vizing定理
定理6.2 (Vizing,1964) 对简单图G有
= 或 + 1 。
证明:(Bollobas证法)不妨设G中 除边uv1外 都已用色 1,2,……, +1 进行了正常边着色。下文中我们恒用Ei表示G中全体色i边的集合。注意到,G 的每个顶点上都至少有一色未表现。令顶点u,v1 上各有色i0,i1 未表现。我 们可逐步找到不同的色、边序列: i0 , i1 , i2 ,……,ij ,…… ; uv1 , uv2 ,uv3 ,……,uvj ,…… 。 vk+1(ik+1) 其中, 色ij 是顶点 vj 上未表现的(任意取定的)一色; vk(ik) 边uvj 上有色ij-1 。 j=2,3,…… 。 ik-1 ik 显然,上述过程至多进行到某q( )次而停止 (无法继续满足上述条件)。 这时只有两种可能: i2 u(i0) (A) 色iq 未表现于顶点u上(即没有一条u的关联边有色iqv3 ): (i3) i 1 重新进行边着色如下, iq-1 no vq(iq) uvj 改着色ij 1 j q-1 v2(i2) 并抹去边uvq 上的色 iq-1 。 v1(i1) 得G中除uvq外的正常( +1)边着色。其中u与vq上色iq 同时不表现。将 v(i)表示 v 上色 i 未表现 uvq 改着色 iq 即得G的正常( +1)边着色。
第8章_有向图

图论及其应用
5
8.1 有向图——习题
10.1.1. 一个简单图有多少个定向图? 10.1.2. 证明: = = 。 10.1.3. 设有向图D中无有向圈,则 d (v ) d (v ) v V v (a) = 0V; (b) 存在一个顶点排序v1,……,v ,使对1 i ,每条 以vi为 头的弧其尾都在{v1,……,vi-1} 中。 10.1.4. 证明:D是双向连通的 D是连通的,且D的每个块 是双向连通的。 10.1.5. D的逆图 是把D中每弧的方向都改为其反向所得的 有向图。试用逆图慨念及习题10.1.3.(a) 来证明: 若有向图D中 无有向圈,则+ = D 。 0 10.1.6. 证明:严格有向图包含长 max{ ,+}的有向路。 10.1.7. 证明:严格有向图中若max{ ,+} = k 1,则 D包含长 k+1 的有向圈。
图论及其应用
第8章 有向图
8.1 有向图
有向图(directed graph;digraph) D =(V,A) V(D) —— 顶点集。 a u v A(D) —— 弧集。 弧a = (u,v):其头为v,其尾为u; 弧a从u连到(join to)v。 有向子图(subdigraph) 有向图D的基础图(underlying graph) 对应于D的无向图G(称D为G的一个定向 (orientation)图)
8.1 有向图
易见,有向图D = (V, A)中顶点间的双向连通性是V上 的一个等价关系,它的等价类确定了V的一个划分 (V1,……,Vm), 使顶点u与v双向连通 u与v 同属某等价类Vi 。 称每个导出子图D[V1],……,D[Vm]为有向图D的一 个双向分支(dicomponent;strong component)。 当D只有一个双向分支时,称D为双向连通的。 易见,D的任二双向分支之间的弧都是同一个方向的。 例
图的着色与染色问题
图的着色与染色问题图的着色与染色问题是图论中的一个经典问题,旨在寻找一种给图中的每个顶点染上不同颜色的方法,使得相邻的顶点具有不同颜色。
本文将介绍图的着色和染色问题的基本概念,讨论几种常见的着色算法,并探讨该问题在实际应用中的一些应用场景。
一、基本概念在介绍图的着色与染色问题之前,首先需要了解一些基本概念。
图是由一组顶点和一组边组成的数据结构,表示了顶点之间的关系。
图可以分为有向图和无向图,其中无向图的边没有方向性,有向图的边具有方向性。
对于图中的每个顶点,可以对其进行染色,也就是给顶点赋予一个颜色值。
染色是为了满足一个重要的条件:相邻的顶点不能具有相同的颜色。
相邻顶点是指在图中由一条边连接的两个顶点。
二、着色算法在解决图的着色问题时,常用的算法有贪心算法、回溯算法和深度优先搜索算法。
下面将分别介绍这三种算法的基本思想和应用场景。
1. 贪心算法贪心算法是一种简单而高效的着色算法。
该算法会选择一个顶点,为其染上一个颜色,然后遍历与该顶点相邻的顶点,为其染色。
不断重复该过程,直到所有顶点都被染色。
贪心算法的应用场景包括地图着色问题和课程表问题。
在地图着色问题中,顶点表示不同的地区,边表示不同地区之间的邻接关系。
要求相邻的地区颜色不同,使用贪心算法可以高效地解决这个问题。
在课程表问题中,顶点表示不同的课程,边表示课程之间的先修关系。
贪心算法可以帮助安排合理的课程表。
2. 回溯算法回溯算法是一种递归的算法,它通过尝试所有可能的颜色组合,直到找到满足条件的染色方案为止。
如果在尝试的过程中发现无法满足条件,则会回溯到上一个状态,重新选择颜色。
回溯算法常用于解决复杂的着色问题,例如地图染色问题和调度问题。
在地图染色问题中,回溯算法可以找到一种合理的地图着色方案。
在调度问题中,回溯算法可以帮助制定一种合理的调度方案,例如安排会议或任务的时间表。
3. 深度优先搜索算法深度优先搜索算法是一种遍历算法,通过从起始顶点开始,沿着一条路径一直搜索到底,然后回溯到上一个顶点,继续搜索其他路径,直到所有顶点都被访问。
图论课件-图的顶点着色
AC
所以, (G) 4
7
1
0.5 n 0
0.5
1 2 1.5 t1 0.5 00
1 0.8
0.6 0.4 x 0.2
注:对图的正常顶点着色,带来的是图的顶点集合的
一种划分方式。所以,对应的实际问题也是分类问题。 属于同一种颜色的顶点集合称为一个色组,它们彼此不 相邻接,所以又称为点独立集。用点色数种颜色对图G 正常着色,称为对图G的最优点着色。
若G1是非正则单图,则由数学归纳,G1是可Δ (G)顶点 正常着色的,从而,G是可Δ (G)正常顶点着色的。
(2) 容易证明:若G是1连通单图,最大度是Δ ,则
(G) (G)
15
1
0.5 n 0
0.5
1 2 1.5 t1 0.5 00
1 0.8
0.6 0.4 x 0.2
(3) Δ (G)≥3
11
1
0.5 n 0
0.5
1 2 1.5 t1 0.5 00
1 0.8
0.6 0.4 x 0.2
(1), (v3 )=3
v1
v6
v5
(2),C(v4)=3,C C(v4) 1, 2, 4,5, k 1
(1), (v4 )=1
v2
(2),C(v5)=1,C C(v5) 2,3, 4,5, k 2
v
块
块
块
G -v
17
1
0.5 n 0
0.5
1 2 1.5 t1 0.5 00
1 0.8
0.6 0.4 x 0.2
由于G本身2连通,所以G-xn的每个仅含有一个割点的块 中均有点与xn邻接。设分属于H1与H2中的点x1与x2,它们与 xn邻接。由于x1与x2分属于不同块,所以x1与x2不邻接。又 因为Δ ≥3,所以G-{x1, x2}连通。
图着色问题的整数规划模型
图着色问题的整数规划模型图着色问题是指给定一个图,如何用有限的颜色对图中的每个顶点进行染色,同时要求相邻的顶点不能具有相同的颜色。
该问题在图论和离散优化领域中具有重要的研究价值和应用意义。
在本文中,我们将介绍一种用整数规划模型来解决图着色问题的方法。
一、问题描述给定一个无向图G=(V,E),其中V是顶点的集合,E是边的集合。
现在需要为图中的每个顶点分配一种颜色,并且要求相邻的顶点之间不能分配相同的颜色。
也就是说,如果两个顶点在图中存在一条边相连,则它们不能分配相同的颜色。
二、整数规划模型为了描述图着色问题的整数规划模型,我们首先定义一组决策变量。
设顶点v属于集合V,颜色c属于集合C,那么决策变量x_vc表示顶点v是否被分配颜色c,取1表示被分配,取0表示未被分配。
接下来,我们可以定义以下约束条件:1. 每个顶点只能被分配一种颜色:对于每个顶点v,有∑(c∈C) x_vc = 1,其中∑表示求和。
2. 相邻的顶点不能分配相同的颜色:对于任意的边(u,v)∈E,有∑(c∈C) x_uc ≠ ∑(c∈C) x_vc。
3. 决策变量的取值范围:x_vc只能取0或1。
4. 目标函数:为了最小化所需的颜色数量,我们可以定义目标函数为最大化∑(v∈V) x_vc。
三、求解方法将图着色问题转化为整数规划模型后,可以使用相应的求解方法来找到最优解。
常用的求解方法包括线性规划、整数规划和混合整数规划等。
对于线性规划,我们忽略决策变量的整数限制,将约束条件和目标函数设计成线性的形式。
然后使用线性规划求解器求解可以得到一个最优解。
但需要注意的是,线性规划得到的解可能不是整数解,需要进一步进行舍入处理。
对于整数规划,我们将决策变量的整数约束加入模型中。
这样可以确保得到的解是整数解。
但整数规划问题通常是NP难问题,求解难度较大。
对于混合整数规划,我们可以采用分支定界、割平面等方法来进行求解。
这些方法可以在规模较大的问题中得到较好的解。
图论中的图的着色与染色问题
图论中的图的着色与染色问题图论是数学的一个分支,研究的是图的性质和图的应用。
在图论中,图的着色与染色问题是一个经典且重要的研究课题。
图的着色问题是指如何用有限的颜色对图的顶点或边进行染色,使得相邻的顶点或边具有不同的颜色。
本文将介绍图的着色与染色问题的基本概念和应用。
一、图的基本概念1. 无向图和有向图无向图由一些顶点和连接这些顶点的边组成,边没有方向性。
而有向图中,边是有方向性的,连接两个顶点的边有始点和终点之分。
2. 邻接矩阵和邻接表邻接矩阵是一种表示图的方法,用一个矩阵表示图中各个顶点之间的连接关系。
邻接表是另一种表示图的方法,用链表的形式表示图中各个顶点之间的连接关系。
二、图的着色问题图的着色问题是指如何用有限的颜色对图的顶点或边进行染色,使得相邻的顶点或边具有不同的颜色。
图的着色问题有以下两种情况:1. 顶点着色对于无向图或有向图的顶点,通过对每个顶点进行染色,使得图中任何相邻的顶点具有不同的颜色。
这里的相邻顶点指的是通过一条边相连的顶点。
2. 边着色对于无向图或有向图的边,通过对每条边进行染色,使得图中任何相邻的边具有不同的颜色。
这里的相邻边指的是有共同始点或终点的边。
三、图的染色算法对于图的着色问题,有不同的染色算法可以解决。
在这里我们介绍两种常用的染色算法:贪心算法和回溯算法。
1. 贪心算法贪心算法是一种基于局部最优策略的算法。
对于图的顶点着色问题,贪心算法的策略是从一个未染色的顶点开始,将其染上一个可用的颜色,并将该颜色标记为已占用,然后继续处理下一个未染色的顶点。
如果当前顶点没有可用的颜色可染,则需要增加一个新的颜色。
2. 回溯算法回溯算法是一种穷举所有可能性的算法。
对于图的着色问题,回溯算法的策略是从一个未染色的顶点开始,尝试不同的颜色进行染色,如果发现染色后与相邻顶点冲突,就回溯到上一个顶点重新尝试其他颜色,直到所有顶点都被染色。
四、图的着色问题的应用图的着色问题在实际中有广泛的应用。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 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<iostream>
#include<fstream>
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<n;++i) //邻接矩阵初始化
for(j=0;j<n;++j)
r[i][j]=-1;
for(i=0;i<n;++i) //输入节点邻接矩阵
for(j=0;j<n;++j)
cin>>r[i][j];
mapcolor(x,r,n);//节点着色
for(i=0;i<n;++i) //输出解
cout<<"color of node "<<i+1<<" : "<<x[i]<<endl;
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<n)//以节点为扫描对象,从第2个节点开始,通过判断和前面已着色的i-1个节点是否冲突,为节点i试探合适的颜色
while(color<=4 && i<n)//对于每一个节点i,从值为color的颜色开始扫描可用的颜色(试探)
{
for(j = 0; j <i; j++) //判断和前i-1个已着色的节点是否存在着色冲突{
if(r[i][j] == 1 && x[j] ==color) //相邻节点,且颜色相同,则跳出循环break;
}
if(j < i)
++color;//下一个欲试探的颜色
else
3
{
x[i]=color;//欲着的颜色和前i-1个已着色的节点不冲突,当前节点着色为color颜色
++i;//准备试探下一个节点
color=1;//颜色重新赋值
}
if(color>4)//没有可用颜色,回溯到上一个节点{
--i;
color=x[i]+1;//倒退后,当前节点下一个试探的颜色}
}
}
输入:
7
0 1 0 0 0 0 1
1 0 1 1 1 1 1
0 1 0 1 0 0 0
0 1 1 0 1 0 0
0 1 0 1 0 1 0
0 1 0 0 1 0 1
1 1 0 0 0 1 0
输出:
验证:上述运行结果图形化结果如下图所示。
颜色号及对应颜色:1:红色;2:绿色;3:淡紫;4:浅蓝色4。