中国地图四色染色问题

中国地图四色染色问题
中国地图四色染色问题

中国地图四色染色问题

一、问题描述

将中国地图用四种不同的颜色红、蓝、绿、黄来染色,要求相邻的省份染色不同,有多少种不同的方案?

二、问题分析

本文将中国地图的34个省、直辖市、自治区、以及特别行政区转化为图论中的图模型。其中每个省、市、自治区、特别行政区用图中的一个结点表示,两个结点间联通仅当两个板块接壤。则问题转化为图论中的染色问题。由于海南、台湾省不与其它任何省份相邻,所以如果除海南、台湾外如果有n种染色方法,那么加上海南和台湾省后,有4*4*n种染色方法。下面考虑除海南和台湾后的32个结点的染色方法。

三、中国地图染色方法

采用分开海南和台湾省的分析方法,一方面的原因是除海南和台湾后的32个结点,可以组成一个联通图,因为海南省和台湾省不和任何其它省份邻接。另一方面,我们建立一个联通图模型后,染色问题可以用深度优先遍历算法DFS,或者广度优先遍历算法BFS来解决,由于该方法的时间复杂度较高,属于暴力法,少考虑两个省份可以减少计算机处理此问题的时间。本文采用DFS算法来解决这个染色问题。

3.1 DFS算法简介

DFS算法是图的一种图的深度遍历算法,即按照往深的地方遍历

一个图,若到一个分支的尽头,则原路返回到最近一个未被遍历的结点,继续深度遍历。

DFS遍历的具体步骤可为下:

1)标记图中所有结点为“未访问”标记。

2)输出起始结点,并标记为“访问”标记

3)起始结点入栈

4)若栈为空,程序结束;若栈不为空,取栈顶元素,若该元素存在未被访问的邻接顶点,则输出一个邻接顶点,并置为“访

问”状态,入栈;否则,该元素退出栈顶。

3.2 染色问题中的DFS算法设计

我们先对任一结点染色,然后用DFS从该结点出发,遍历该图,遍历的下一结点颜色染为与之相邻的结点不同的颜色即可。如果该结点无法染色则回到上一个结点重新染色,直到所有的结点都被染色即可。最后统计染色种数。

染色问题的算法伪代码可以描述如下:

color_DFS(当前染色结点):

for i in 所有颜色

{ while j的已染色邻接点

if 结点j相邻接点被染成i颜色

标记并break

if 未被标记

{

当前结点染为i色

if 当前结点为最后一个结点

end

else

color_DFS(next)

}

3.3 数据结构设计

为了实现DFS染色算法,我们需要设计相应的数据结构。由于图的结点不多,只有32个,我们采用图的邻接矩阵来存储该图,记为map[33][33],map[0]不存储数据,如果两结点i,j相邻,map[i][j]=1,否则map[i][j]=0。

为了便于计算机编程,我们将每一个地名用相应结点号来表示,1:"新疆",2:"西藏",3:"青海",4:"甘肃",5:"内蒙古",6:"宁夏",7:"黑龙江",8:"吉林",9:"辽宁",10:"河北",11:"北京",12:"山西",13:"陕西",14:"山东

",15:"天津",16:"河南",17:"安徽",18:"江苏",19:"上海",20:"浙江",21:"福建",22:"江西",23:"广东",24:"湖南",25:"湖北",26:"重庆",27:"四川",28:"贵州",29:"云南",30:"广西",31:"香港",32:"澳门"。

新疆和西藏相邻,那么我们就可以用map[1][2]=1来表示。

同样地,一种颜色我们也可以用一个数字来表示,在这里,我们用数字来代表颜色,比如1-红、2-蓝、3-绿、4-黄。

四、C语言代码实现

#include

#include

using namespace std;

char name[][10]={"","新疆","西藏","青海","甘肃","内蒙古","宁夏","黑龙江","吉林","辽宁","河北","北京","山西","陕西","山东","天津","河南","安徽","江苏","上海","浙江","福建","江西","广东","湖南","湖北","重庆","四川","贵州","云南","广西","香港","澳门"};

char color[][4]={"","红","蓝","绿","黄"};

int map[33][33];

int vis[33];

int n,m;

long long cnt;//染色方法设置为long long防止溢出

void init_map()

{

map[1][2]=map[2][1]=1;//表示新疆和西藏连通

map[1][3]=map[3][1]=1;

map[1][4]=map[4][1]=1;

map[2][3]=map[3][2]=1;

map[2][27]=map[27][2]=1;

map[2][29]=map[29][2]=1;

map[3][4]=map[4][3]=1;

map[3][27]=map[27][3]=1;

map[4][5]=map[5][4]=1;

map[4][6]=map[6][4]=1;

map[4][13]=map[13][4]=1;

map[4][27]=map[27][4]=1;

map[5][6]=map[6][5]=1;

map[5][7]=map[7][5]=1;

map[5][8]=map[8][5]=1;

map[5][9]=map[9][5]=1;

map[5][10]=map[10][5]=1;

map[5][12]=map[12][5]=1;

map[5][13]=map[13][5]=1;

map[6][13]=map[13][6]=1;

map[7][8]=map[8][7]=1;

map[8][9]=map[9][8]=1;

map[9][10]=map[10][9]=1;

map[10][11]=map[11][10]=1;

map[10][12]=map[12][10]=1;

map[10][14]=map[14][10]=1;

map[10][15]=map[15][10]=1;

map[10][16]=map[16][10]=1;

map[11][15]=map[15][11]=1;

map[12][13]=map[13][12]=1;

map[12][16]=map[16][12]=1;

map[13][16]=map[16][13]=1;

map[13][25]=map[25][13]=1;

map[13][26]=map[26][13]=1;

map[13][27]=map[27][13]=1;

map[14][16]=map[16][14]=1;

map[14][17]=map[17][14]=1;

map[14][18]=map[18][14]=1;

map[16][17]=map[17][16]=1;

map[16][25]=map[25][16]=1;

map[17][18]=map[18][17]=1;

map[17][20]=map[20][17]=1;

map[17][22]=map[22][17]=1;

map[17][25]=map[25][17]=1;

map[18][19]=map[19][18]=1;

map[18][20]=map[20][18]=1;

map[19][20]=map[20][19]=1;

map[20][21]=map[21][20]=1;

map[20][22]=map[22][20]=1;

map[21][22]=map[22][21]=1;

map[21][23]=map[23][21]=1;

map[22][23]=map[23][22]=1;

map[22][24]=map[24][22]=1;

map[22][25]=map[25][22]=1;

map[23][24]=map[24][23]=1;

map[23][30]=map[30][23]=1;

map[23][31]=map[31][23]=1;

map[23][32]=map[32][23]=1;

map[24][25]=map[25][24]=1;

map[24][26]=map[26][24]=1;

map[24][28]=map[28][24]=1;

map[24][30]=map[30][24]=1;

map[25][26]=map[26][25]=1;

map[26][27]=map[27][26]=1;

map[26][28]=map[28][26]=1;

map[27][28]=map[28][27]=1;

map[27][29]=map[29][27]=1;

map[28][29]=map[29][28]=1;

map[28][30]=map[30][28]=1;

map[29][30]=map[30][29]=1; }

void dfs(int now)//当前结点染色

{

int i,j,k;

for(i = 1; i<=n; i++)//n种颜色

{

int flag = 1;

for(j = 1; j

{

if(map[j][now] && vis[j]==i)//j的邻接点被染为第i种颜色

{

flag=0;

break;

}

}

if(flag)

{

vis[now]=i;//当前结点染为第i种颜色

if(now == m)//全部结点都已染色

{

cnt++;//种数+1

/*if(cnt>=5)

exit(0);

for(k=1;k<=m;k++)//输出4组染色结果

{

printf("%s-%s ",name[k],color[vis[k]]);

if(k%8==0)

printf("\n");

}

printf("\n");*/

}

else

dfs(now+1);//下一个结点染色

}

}

}

int main()

{

n=4;//4种颜色

m=32;//32个省份

memset(map,0,sizeof(map));//地图全部置为0,表示未连通

memset(vis,0,sizeof(vis)); //每个顶点未染色

init_map(); //初始化图

cnt = 0;//染色方法数

dfs(1);//从结点1开始染色

printf("%lld\n",cnt);

return 0;

}

五、结果分析

本次实验在MAC_OS操作系统进行实验,处理器为2.8GHz Intel i7处理器,其计算结果为360516096,耗时约150s。如果加上海南省和台湾省,其最终的计算结果为360516096*16=5768257536。

图1是部分染色结果(不包括台湾、海南省),事实上台湾海南省的染色任意。

图1 32个结点部分染色结果

六、总结

通过这个图论染色问题,加深了我对图论知识的理解。我明白了如何将理论知识应用到实际问题中来。虽然我以前也做过类似的地图染色实验,但是在这过程中我发现了自己的一些不足,比如说不够仔

细,在构建一个邻接矩阵中多次忘记一些邻接边,以至于邻接矩阵错误。

总之,这次实验加强了我的动手能力以及解决问题的能力,加深了我对图论知识的理解和数据结构的应用能力,总之我收获颇多。

中国分省行政区划及区划地图(图形版)

北京市行政区划及区划地图 北京简称京。面积1.68万平方千米,人口1382万(2000年)。总计16市辖区2县 市辖区东城区西城区崇文区宣武区朝阳区海淀区丰台区石景山区门头沟区房山区通州区顺义区昌平区大兴区怀柔区平谷区 县密云县(密云镇) 延庆县(延庆镇) 天津市行政区划及区划地图

天津,简称津。面积1.1万多平方千米,人口1001万(2000年)。总计15个市辖区3个县 市辖区和平区河东区河西区南开区河北区红桥区塘沽区汉沽区大港区东丽区西青区北辰区津南区武清区(杨村镇) 宝坻区(城关镇) 县静海县(静海镇) 宁河县(芦台镇) 蓟县(城关镇) 河北省行政区划及区划地图

河北,简称冀,省会石家庄市。面积19万多平方千米,人口6744万(2000年)。总计11个地级市36市辖区 22县级市 108县 6自治县 石家庄市 长安区桥东区桥西区新华区 裕华区井陉矿区 辛集市藁城市晋州市新乐市 鹿泉市 平山县(平山镇) 井陉县(微水镇) 栾城县(栾城镇) 正定县(正定镇) 行唐县(龙州镇) 灵寿县(灵寿镇) 高邑县(高邑镇) 赵县(赵州镇) 赞皇县(赞皇镇) 深泽县(深泽镇) 无极县(无极镇) 元氏县(槐阳镇) 唐山市 路北区路南区古冶区开平区 丰润区丰南区(胥各庄镇) 遵化市迁安市 迁西县(兴城镇) 滦南县(倴城镇) 玉田县(玉田镇) 唐海县(唐海镇) 乐亭县(乐亭镇) 滦县(滦州镇) 秦皇岛市海港区山海关区北戴河区 昌黎县(昌黎镇) 卢龙县(卢龙镇) 抚宁县(抚宁镇) 青龙满族自治县(青龙镇) 邯郸市从台区复兴区邯山区峰峰矿区

武安市 邯郸县(南堡乡东小屯村) 永年县(临洺关镇) 曲周县(曲周镇) 馆陶县(馆陶镇) 魏县(魏城镇) 成安县(成安镇) 大名县(大名镇) 涉县(涉城镇) 鸡泽县(鸡泽镇) 邱县(新马头镇) 广平县(广平镇) 肥乡县(肥乡镇) 临漳县(临漳镇) 磁县(磁州镇) 邢台市 桥东区桥西区 南宫市沙河市 邢台县(邢台市桥东区) 柏乡县(柏乡镇) 任县(任城镇) 清河县(葛仙庄镇) 宁晋县(凤凰镇) 威县(洺州镇) 隆尧县(隆尧镇) 临城县(临城镇) 广宗县(广宗镇) 临西县(临西镇) 内丘县(内丘镇) 平乡县(丰州镇) 巨鹿县(巨鹿镇) 新河县(新河镇) 南和县(和阳镇) 保定市 新市区南市区北市区 涿州市定州市安国市高碑店市满城县(满城镇) 清苑县(清苑镇) 涞水县(涞水镇) 阜平县(阜平镇) 徐水县(安肃镇) 定兴县(定兴镇) 唐县(仁厚镇) 高阳县(高阳镇) 容城县(容城镇) 涞源县(涞源镇) 望都县(望都镇) 安新县(安新镇) 易县(易州镇) 曲阳县(恒州镇) 蠡县(蠡吴镇) 顺平县(蒲阳镇) 博野县(博陵镇) 雄县(雄州镇) 张家口市 桥西区桥东区宣化区下花园区宣化县(张家口市宣化区) 康保县(康保镇) 张北县(张北镇) 阳原县(西城镇) 赤城县(赤城镇) 沽源县(平定堡镇) 怀安县(柴沟堡镇) 怀来县(沙城镇) 崇礼县(西湾子镇) 尚义县(南壕堑镇) 蔚县(蔚州镇) 涿鹿县(涿鹿镇) 万全县(孔家庄镇) 承德市 双桥区双滦区鹰手营子矿区 承德县(下板城镇) 兴隆县(兴隆镇) 隆化县(隆化镇) 平泉县(平泉镇) 滦平县(滦平镇) 丰宁满族自治县(大阁镇) 围场满族蒙古族自治县(围场镇) 宽城满族自治县(宽城镇)

(推荐)中国分省行政区划及区划地图

1. 北京市行政区划及区划地图 北京简称京。面积1.68万平方千米,人口1382万(2000年)。总计16市辖区2县 市辖区东城区西城区崇文区宣武区朝阳区海淀区丰台区石景山区门头沟区房山区通州区顺义区昌平区大兴区怀柔区平谷区 县密云县(密云镇) 延庆县(延庆镇) 2.天津市行政区划及区划地图

天津,简称津。面积1.1万多平方千米,人口1001万(2000年)。总计15个市辖区3个县 市辖区和平区河东区河西区南开区河北区红桥区塘沽区汉沽区大港区东丽区西青区北辰区津南区武清区(杨村镇) 宝坻区(城关镇) 县静海县(静海镇) 宁河县(芦台镇) 蓟县(城关镇) 3.河北省行政区划及区划地图

河北,简称冀,省会石家庄市。面积19万多平方千米,人口6744万(2000年)。总计11个地级市36市辖区 22县级市 108县 6自治县 石家庄市 长安区桥东区桥西区新华区 裕华区井陉矿区 辛集市藁城市晋州市新乐市 鹿泉市 平山县(平山镇) 井陉县(微水镇) 栾城县(栾城镇) 正定县(正定镇) 行唐县(龙州镇) 灵寿县(灵寿镇) 高邑县(高邑镇) 赵县(赵州镇) 赞皇县(赞皇镇) 深泽县(深泽镇) 无极县(无极镇) 元氏县(槐阳镇) 唐山市 路北区路南区古冶区开平区 丰润区丰南区(胥各庄镇) 遵化市迁安市 迁西县(兴城镇) 滦南县(倴城镇) 玉田县(玉田镇) 唐海县(唐海镇) 乐亭县(乐亭镇) 滦县(滦州镇) 秦皇岛市海港区山海关区北戴河区 昌黎县(昌黎镇) 卢龙县(卢龙镇) 抚宁县(抚宁镇) 青龙满族自治县(青龙镇) 邯郸市从台区复兴区邯山区峰峰矿区

武安市 邯郸县(南堡乡东小屯村) 永年县(临洺关镇) 曲周县(曲周镇) 馆陶县(馆陶镇) 魏县(魏城镇) 成安县(成安镇) 大名县(大名镇) 涉县(涉城镇) 鸡泽县(鸡泽镇) 邱县(新马头镇) 广平县(广平镇) 肥乡县(肥乡镇) 临漳县(临漳镇) 磁县(磁州镇) 邢台市 桥东区桥西区 南宫市沙河市 邢台县(邢台市桥东区) 柏乡县(柏乡镇) 任县(任城镇) 清河县(葛仙庄镇) 宁晋县(凤凰镇) 威县(洺州镇) 隆尧县(隆尧镇) 临城县(临城镇) 广宗县(广宗镇) 临西县(临西镇) 内丘县(内丘镇) 平乡县(丰州镇) 巨鹿县(巨鹿镇) 新河县(新河镇) 南和县(和阳镇) 保定市 新市区南市区北市区 涿州市定州市安国市高碑店市满城县(满城镇) 清苑县(清苑镇) 涞水县(涞水镇) 阜平县(阜平镇) 徐水县(安肃镇) 定兴县(定兴镇) 唐县(仁厚镇) 高阳县(高阳镇) 容城县(容城镇) 涞源县(涞源镇) 望都县(望都镇) 安新县(安新镇) 易县(易州镇) 曲阳县(恒州镇) 蠡县(蠡吴镇) 顺平县(蒲阳镇) 博野县(博陵镇) 雄县(雄州镇) 张家口市 桥西区桥东区宣化区下花园区宣化县(张家口市宣化区) 康保县(康保镇) 张北县(张北镇) 阳原县(西城镇) 赤城县(赤城镇) 沽源县(平定堡镇) 怀安县(柴沟堡镇) 怀来县(沙城镇) 崇礼县(西湾子镇) 尚义县(南壕堑镇) 蔚县(蔚州镇) 涿鹿县(涿鹿镇) 万全县(孔家庄镇) 承德市 双桥区双滦区鹰手营子矿区 承德县(下板城镇) 兴隆县(兴隆镇) 隆化县(隆化镇) 平泉县(平泉镇) 滦平县(滦平镇) 丰宁满族自治县(大阁镇) 围场满族蒙古族自治县(围场镇) 宽城满族自治县(宽城镇)

相关文档
最新文档