作者:冬瓜争做全栈瓜

链接:https://mp.weixin.qq.com/s/36QRk4Kw5YDNdwxjnFCXfg

按往常,今天应该开工了,但这个春节假期特别长,在家待傻了嘛?新型病毒让人不敢出门玩儿了,但为什么冠状病毒从湖北出发传播这么快?抛开春运的原因,单就地理问题来看下这个问题吧。

友情提醒下,今天要讲的是图论问题。难吗?不难不难。

虽然是解题用的语言不是你们熟悉的Java,但是算法思路还是可以好好学习一下。不能随意出门儿了,动脑不能停呀。

九省通衢的武汉

这两天新型冠状病毒真的是让人心惊胆战。病毒传播速度的快从官方给出的数字就能体现出来。在传播的背后其实还隐藏着这么一个问题:为什么很多人都会从湖北出发,或者途经湖北省呢?

大约在去年年底,我在微博上看见了这么一个热搜:武汉到任一省级行政区最多只需要跨越两个省级行政区

微博热搜 #武汉到任一省级行政区最多跨两个

这句话听起来有点绕,其实就是从湖北省出发,到任一一个省份,途中只需要经过小于等于 2 个省份就能到达。在这条微博上还给了三个例子:

几个例子

当然这里有一些不严谨的地方就是广西省和海南省其实是隔海相望的,在这里我们也假定它俩是相邻的。那事实真的是如此吗?

模型抽象

我们可以把所有省份全部都抽象成一个节点,然后将相邻的节点建边。这样我们就将中国省级行政区抽象成了多个节点。下面的动图展示了建图过程:

模拟建图过程

为了建立图的边连接关系,我将所有省级行政区的相邻关系已经整理了出来,其结果如下:

北京市:河北省、天津市
天津市:北京市、河北省
上海市:浙江省、江苏省
重庆市:四川省、贵州省、陕西省、湖北省、湖南省
河北省:山东省、河南省、山西省、内蒙古自治区、辽宁省、天津市、北京市
山西省:内蒙古自治区,陕西省,河南省,河北省
辽宁省:吉林省、内蒙古自治区、河北省
吉林省:内蒙古自治区、辽宁省、黑龙江省
黑龙江省:吉林省、内蒙古自治区
江苏省:山东省、安徽省、浙江省、上海市
浙江省:江苏省、安徽省、上海市、江西省、福建省
安徽省:山东省、江苏省、浙江省、江西省、湖北省、河南省
福建省:浙江省、江西省、山东省、台湾省(隔海相望)
江西省:安徽省、浙江省、福建省、广东省、湖南省、湖北省
山东省:河北省、河南省、安徽省、江苏省
河南省:河北省、山东省、江苏省、安徽省、湖北省、陕西省、山西省
湖北省:河南省、安徽省、江西省、湖南省、重庆市、陕西省
湖南省:湖北省、江西省、广东省、广西壮族自治区、贵州省、重庆市
广东省:福建省、江西省、湖南省、广西壮族自治区、海南省(隔海相望)、香港市、澳门市
海南省:广东省
四川省:青海省、甘肃省、陕西省、重庆市、贵州省、云南省、新疆维吾尔自治区、西藏自治区
贵州省:四川省、重庆市、湖南省、广西壮族自治区、云南省
云南省:西藏自治区、四川省、贵州省、广西壮族自治区
陕西省:内蒙古自治区、陕西省、河南省、湖北省、重庆市、四川省、甘肃省、宁夏回族自治区
甘肃省:内蒙古自治区、宁夏回族自治区、陕西省、四川省、青海省、新疆维吾尔自治区
青海省:新疆维吾尔自治区、甘肃省、四川省、西藏自治区
台湾省:福建省
内蒙古自治区:甘肃省、宁夏回族自治区、陕西省、陕西省、河北省、辽宁省、吉林省、黑龙江省
广西壮族自治区:云南省、贵州省、湖南省、广东省
西藏自治区:新疆维吾尔自治区、青海省、四川省、云南省
宁夏回族自治区:内蒙古自治区、陕西省、甘肃省
新疆维吾尔自治区:甘肃省、青海省、西藏自治区
香港市:广东省
澳门市:广东省

文本数据预处理

上面的数据文本数据来源有两个地方,一个是通过 Google 搜出的,另外一部分是笔者通过省级行政区板块图自己数出来的。

desc = """北京:河北、天津
天津:北京、河北
上海:浙江、江苏
重庆:四川、贵州、陕西、湖北、湖南
河北:山东、河南、山西、内蒙古、辽宁、天津、北京
山西:内蒙古、陕西、河南、河北
辽宁:吉林、内蒙古、河北
吉林:内蒙古、辽宁、黑龙江
黑龙江:吉林、内蒙古
江苏:山东、安徽、浙江、上海
浙江:江苏、安徽、上海、江西、福建
安徽:山东、江苏、浙江、江西、湖北、河南
福建:浙江、江西、山东、台湾
江西:安徽、浙江、福建、广东、湖南、湖北
山东:河北、河南、安徽、江苏
河南:河北、山东、江苏、安徽、湖北、陕西、山西
湖北:河南、安徽、江西、湖南、重庆、陕西
湖南:湖北、江西、广东、广西、贵州、重庆
广东:福建、江西、湖南、广西、海南、香港、澳门
海南:广东
四川:青海、甘肃、陕西、重庆、贵州、云南、新疆、西藏
贵州:四川、重庆、湖南、广西、云南
云南:西藏、四川、贵州、广西
陕西:内蒙古、陕西、河南、湖北、重庆、四川、甘肃、宁夏
甘肃:内蒙古、宁夏、陕西、四川、青海、新疆
青海:新疆、甘肃、四川、西藏
台湾:福建
内蒙古:甘肃、宁夏、陕西、陕西、河北、辽宁、吉林、黑龙江
广西:云南、贵州、湖南、广东
西藏:新疆、青海、四川、云南
宁夏:内蒙古、陕西、甘肃
新疆:甘肃、青海、西藏
香港:广东
澳门:广东
"""import redatas = desc.split('\n')
cities = {}# 数据处理
for line in datas:m = re.match(r'^(.+?):(.+?)$', line)if m:current_city = m.groups(2)[0]link_cities_data = m.groups(2)[1]current_link_cities = []for link_city in link_cities_data.split('、'):current_link_cities.append(link_city)cities[current_city] = current_link_citiesprint(cities)"""
{'北京': ['河北', '天津'], '天津': ['北京', '河北']...
"""

通过对字符串的处理和正则匹配捕获,我们获得一个字典,Key 是每个省级行政区,Value 是一个数组,也就是和它相邻的省级行政区。如此,我们将一份省级行政区相邻的关系数据转换成为了一个无向图。

单源最短路的使用

所谓单源最短路就是计算单一起点(源点)到图中任一一个节点的最短路径是多少的算法。具体在刷题时或者信息学竞赛中常用的只有三种算法:Dijkstra 算法、Bellman-Ford 算法以及 SPFA 算法。这些算法我会在后续专门讲解单源最短路时对每个算法逐一讲述,本文只是一个对单源最短路算法的一个最简单的实践和应用。

继续来思考“到任一省级行政区最多只需要跨越两个省级行政区“这句话,转换成图的描述,其实就是到任一节点的最短路径上,只有小于等于 4 个节点、3 条边。更进一步的,假设我们每一条边的权值都为 1 ,那么只要满足单源到任一节点的最短路径是 ≤ 3 即可证明。

单源最短路

这里我使用 Dijkstra 算法来做此次验证过程。我先给出代码,在后文中再做简单的解释:

# ... 接上文数据处理代码# 节点离散化
city_hash = {}
index = 0
for city in cities.keys():city_hash[city] = indexindex += 1
re_city_hash = {v: k for k, v in city_hash.items()}# 描述图
class Edge:def __init__(self, to: int, cost: int):self.to = toself.cost = costINF: int = 10 ** 8  # 代表无限大
V: int = len(city_hash)  # 节点数
G: [[Edge]] = [[] for _ in range(V)]  # 临界表
d: [int] = [INF] * V  # 最短距离# 建图
for f, tos in cities.items():for to in tos:G[city_hash[f]].append(Edge(to=city_hash[to], cost=1))# 最短路算法
import queue
def dijkstra(s: int):que: queue.PriorityQueue = queue.PriorityQueue()d[s] = 0que.put((0, s))while que.qsize() > 0:p = que.get()v = p[1]for i in range(len(G[v])):e: Edge = G[v][i]# 松弛操作if d[e.to] > d[v] + e.cost:d[e.to] = d[v] + e.costque.put((d[e.to], e.to))dijkstra(s=16)
# print(city_hash)
for i, k in enumerate(d):print(f'{re_city_hash[i]}: {k}', end='\t')"""
北京: 3
天津: 3
上海: 3
重庆: 1
河北: 2
山西: 2
辽宁: 3
吉林: 3
黑龙江: 3
江苏: 2
浙江: 2
安徽: 1
福建: 2
江西: 1
山东: 2
河南: 1
湖北: 0
湖南: 1
广东: 2
海南: 3
四川: 2
贵州: 2
云南: 3
陕西: 1
甘肃: 2
青海: 3
台湾: 3
内蒙古: 2
广西: 2
西藏: 3
宁夏: 2
新疆: 3
香港: 3
澳门: 3
"""

上述代码的简单说明

使用二维数组

G: [[Edge]] = [[] for _ in range(V)]  # 临界表

这段代码中,G 的第一维代表每一个节点,第二维是一个数组,代表所有的边。其实这种结构就巧妙的描述了一个图节点数据结构。其实这里是利用了 Python 中的 List 可扩容的特点,比较巧妙的将节点组成了一个“链式“结构(其实就是下标的连续性)。

这种图描述的数据结构在信息学竞赛中有一个独特的名字叫:链式前向星(邻接表的另一种表达方式),不同于以往邻接表的方式就是遍历方式。

什么是松弛操作?

if d[e.to] > d[v] + e.cost:d[e.to] = d[v] + e.cost

我们通过一种类比来解释一下什么是松弛:假设墙上有如图 4 个钉子,一个橡皮筋现在使用交叉的方式从钉子 1 绑到钉子 2,再从钉子 2 绑到钉子四。现在我将钉子 2 上绑的皮筋摘下换成钉子 3,于是橡皮筋由此得到松弛。

橡皮筋的松弛状态

这个比喻十分形象。假设我们将四个钉子作为四个节点,而目标是从节点 1 途经节点 2 或者 节点 3 走到节点 4 ,此时最短路径就是 1 → 3 → 4。而对应的,这个松弛操作就是在反复的更新 1 → 4 的最短路径。

回归到 Dijkstra 算法,这里的松弛操作是对边的一种松弛。

回归到实际问题

我们通过对省级行政区抽象成图,并且给每一条边赋权,从而验证了武汉到任一一个省级行政区最多只需要跨越两个省级行政区的冷知识。所以从一定角度上,也解释了为什么此次肺炎传播速度之快的些许原因。

当然也许你会说,每个省份也有面积的大小之分,所以单从省级跨越的个数角度是十分不严谨的。当然确实是这样,这里只是想通过最短路算法的角度,来简单的验证这个问题,实际问题肯定还需要具体的分析,才能证明传播速度之快的结论,比如:春运客流量猛增华南海鲜市场到汉口火车站的距离只有 1 公里等等。这所有的一切都在告诉大家要注意个人防护,戴口罩、勤洗手!

最后祝大家身体健康。

近期:
新型肺炎确诊患者相同行程查询工具上线了互联网公司延迟节后上班时间,有你的厂么?
正月初四 | 感谢所有支持wuhan2020项目的朋友!我们招换更多人加入!

今日问题:

放到10号开工的厂,扣你们的年休假么?

专属升级社区:《这件事情,我终于想明白了》 

为什么冠状病毒从湖北出发传播这么快?相关推荐

  1. 神经网络反向传播为什么快

    神经网络反向传播为什么快 为什么从后往前算梯度而不是从前往后算梯度? 首先要有链式法则的认知.然后举个最简单的例子,每个神经元都会有激活函数,当系数(比如w)更新,根据链式求导法则,最终的loss对w ...

  2. 趣图:众志成城,笑战疫情

    码个蛋(codeegg) 第 876 次推文 战疫情,先学好数学 今年最Fasion的春联 码仔,03年抢的盐还没吃完呢 2020最强带货网红! 若是那敌人来了,迎接他的有... 来自超市内心的哭诉 ...

  3. CEJ:西安理工赵亚乾组冠状病毒在水中传播特征、可能遏制策略与研究挑战

    杂志:Chemical Engineering Journal [IF: 10.652] 第一作者:嵇斌 通讯作者:赵亚乾 通讯单位:西安理工大学 论文DOI:https://doi.org/10.1 ...

  4. 新型冠状病毒全球实时跟踪地图,多国研发疫苗,在中国或致8042例感染,爆发峰值预计2月中上旬 | 最新nCoV研究大汇总...

    导读 约翰·霍普金斯大学的全球冠状病毒实时扩散地图 新型冠状病毒溯源取得阶段性进展,武汉华南海鲜市场存在大量新型冠状病毒 多国加紧研发新型冠状病毒疫苗和治疗药物 北大课题组:新型冠状病毒中间宿主或为水 ...

  5. 新型冠状病毒传染性有多强?何时达到峰值?来看一下数学和统计建模结果

    点击我爱计算机视觉标星,更快获取CVML新技术 本文转载自机器之心. 机器之心报道 参与:张倩.杜伟 「在家待着就能为国家做贡献」其实不只是一句玩笑话.在疫情肆虐的这几天里,国内外的流行病学家.统计学 ...

  6. 百兆以太网口通信速率_以太网发送速率(传输速率)和传播速率

    发送速率(传输速率)和传播速率 在通信领域术语上,较为规范的说法,发送速率和传输速率是同一个含义. 1.发送速率(传输速率)是指主机或路由器往(向)数字信道上发送数据的速度,也称为数据率或比特,单位是 ...

  7. 新型冠状病毒感染性肺炎来势汹汹,我们该如何应对?

    本来今天不想更文的,毕竟放假的看的人也少了,不过在春运期间,新型冠状病毒感染扩散的有点快. 就在昨日凌晨,北京.广东.武汉接连发布新型冠状病毒肺炎情况. 其中,武汉 18.19 日新确诊病例 136 ...

  8. 计算机声音处理说课稿,《声音的产生与传播》说课稿

    一.教材分析 本节内容是声音的产生与传播,每一部分都是以问题开始,通过实验与观察,得出结论,再与生活和自然相联系.对于声音的产生,教材通过学生熟悉的声现象创造声音的情境,激发学生的好奇心,提出声音的产 ...

  9. 新型冠状病毒传染性有多强?何时达到疫情峰值?来看一下数学和统计建模结果...

    我是夕小瑶,一只热爱科研和AI的小狐狸 来源 | 机器之心(id: almosthuman2014) 引语:在疫情肆虐的这几天里,国内外的流行病学家.统计学家都没闲着,他们基于疫情爆发初期的一些数据建 ...

最新文章

  1. Sublime Text 无法使用Package Control或插件安装失败的解决方法
  2. socket函数介绍
  3. java插入时间 mssql_JAVA操作数据库Datetime数据
  4. 李战java_【阿里李战】解剖JavaScript中的 null 和 undefined
  5. Sysbench 1.0.15安装及使用
  6. 文件描述符、函数open和openat
  7. CVE-2021-21871: PowerISO 内存越界写漏洞
  8. 【设计模式】适配器模式(Adapter Pattern)
  9. datatables 添加时间按钮_Java 添加页面跳转按钮到PDF文档
  10. LINUX使用gpg签名校验文件
  11. Object C中文件后缀名
  12. 惠普局域网共享打印机设置_打印机共享怎么设置 惠普打印机共享设置步骤介绍【详解】...
  13. 如何开发一套完整的医疗远程会诊系统方案
  14. 雷电4.0 Fiddler https抓包详解(绝对可行)
  15. 2021年氯化工艺考试题库及氯化工艺考试试卷
  16. 两个无线路由器dhcp服务器,两个无线路由器怎么桥接
  17. python123随机密码生成_Python生成对应随机密码文件
  18. Vue 图片懒加载 v-lazy
  19. DFX:面向产品生命周期的设计
  20. MyBatis-第三章 动态SQL

热门文章

  1. HAN:Heterogeneous Graph Attention Network 算法理论
  2. PHP 简单案例[3]
  3. python编辑距离正则匹配_(C/C++学习)33.编辑距离和正则表达式匹配分析
  4. 学计算机提升,【思想提升】学计算机,就是做计算机的吗?
  5. 古风男孩美名推荐分享
  6. 喜提一份 ‘凡尔赛’ 式的搜广推面经!
  7. verilog复习与vhdl入门
  8. TL4050B25QDBZRQ1
  9. 小程序php好物优购毕业设计-附源码191755
  10. 3-8 译码器,与4-16译码器