
发表日期: 2021-04-17 09:56:21 浏览次数:124
正定网站制作【正定网站优化】正定建网站、正定微信公众号运营、正定网页设计、正定微信小程序商城
正定县,河北省石家庄市辖县,位于太行山东麓的山前倾斜平原、山前冲积扇的中上部,因“真正安定”之意得名 [1-2] ;正定县位于东经114°23′~114°43′,北纬38°6′~38°22′,总面积486平方千米,气候型为温带季风气候,四季分明,多年平均气温13.1℃,多年平均降水量550毫米 [3] ;截至2020年10月,正定县下辖2个街道、3个镇和5个乡,境内设有中国(河北)自由贸易试验区正定片区和正定新区;截至2019年末,正定县常住人口为51.7万人 [1] 。
正定县前身为真定县,有1600多年的建城史,最初为鲜虞国都城,后为中山国都城,建县始于秦始皇统一中国后设立的东垣县,“真定”一名始于汉高祖十一年(前196年)改东垣县为真定县,最终于清雍正元年(1723年)改为现名 [2] 。正定县是京津冀城市群、石家庄都市圈的重要城镇,境内建有石家庄正定国际机场,有京广高速铁路过境 [4] 。正定县有“九楼四塔八大寺,二十四座金牌坊”,有“古建艺术宝库”美称 [1] 。
2020年上半年,正定县财政收入为35.7亿元,同比增长5.8%;一般公共预算收入为26.9亿元,同比增长10.1%;固定资产投资为116.2亿元,同比增长11%;服务业增加值为100.3亿元,同比增长11%;规模以上高新技术产业增加值达5.9亿元,同比增长18%;社会消费品零售总额达40.8亿元,同比增长10%;外贸进出口总额达91亿元,同比增长366%;城乡居民人均可支配收入分别为18146元和10260元,同比增长8.2%和8.7% [5] 。
在本节中,我们会看到如何利用深度优先搜索快速解决一些问题。就像之前那样,这里也是用n 表示图的节点数,并用m 表示节点数与弧数间的较大者,特别要指出的是,假设n≤m 总是成立的。这里介绍的算法对用邻接表表示的图来说都要花O(m)的时间。第一个算法可以确定有向图是否为无环的。然后对那些无环图,我们会看到如何找出其节点的拓扑排序(拓扑排序在7.10节讨论过,我们会找个恰当的时机回顾一下其定义)。我们还要展示如何计算图的传递闭包(概念还是见7.10节),以及如何比用9.4中给出的算法更快地找到无向图的连通分支。
在对有向图G 进行深度优先搜索期间,可以在O(m)的时间内为所有节点指定后序编号。回想一下9.6节的内容,我们发现尾部按后序小于等于其头部的弧只有后向弧。只要某图存在后向弧u→v,其中v 的后序编号不小于u 的后序编号,该图中就一定存在环路,如图9-35所示。这条环路是由从u 到v 的弧以及树中从v 到其子孙u 的路径组成的。

图 9-35 每条后向弧都可以与树向弧一起构成环路
这个命题反过来也是成立的,也就是说,如果图中存在环路,那么就肯定存在后向弧。要知道原因,先假设存在某环路,比方说v1→v2→…→vk→v1,并设对i=1、2、…、k,节点vi 的后序编号为pi 。如果k=1,也就是说,环路为一条弧,那么在图G 的任意深度优先表示中v1→v1都肯定是后向弧。
如果k>1,假设v1→v2,v2→v3,等等,直到vk-1→vk 这些弧都不是后向弧。那么每条弧的头部按后序都先于其尾部,而且后序编号p1、p2、…、pk 形成了递减序列。特别要说的是,pk< p1。然后考虑完成该环路的弧vk→v1。其尾部的后序编号为pk,要小于其头部的后序编号p1,所以这条弧是后向弧。这就证明了在环路中肯定存在后向弧。
这样一来,在计算了所有节点的后序编号后,只要检查所有弧,看看有没有弧的尾部按后序小于等于其头部。如果有,我们就找到了后向弧,而且该图是有环图。如果没有这样的弧,该图就是无环图。图9-36展示了测试外部定义的图G 是否为无环图的函数,它所使用的表示图的数据结构与9.6节中描述的相同。它还利用了图9-33中定义的dfsForest函数计算G 中节点的后序编号。
BOOLEAN testAcyclic(GRAPH G)
{
NODE u, v; /* u会行经所有的节点 */
LIST p; /* p指向与u对应的邻接表中的各个单元,
v是该邻接表中的节点 */(1) dfsForest(G);(2) for (u = 0; u < MAX; u++) {(3) p = G[u].successors;(4) while (p != NULL) {(5) v = p->nodeName;(6) if (G[u].postorder <= G[v].postorder)(7) return FALSE;(8) p = p->next;
}
}(9) return TRUE;
}复制代码图 9-36 确定图G 是否无环的函数
在第(1)行调用dfsForest计算后序编号之后,我们会在第(2)行到第(8)行的循环中检查各节点u。指针p 会沿着u 对应的邻接表向下行进,而且在第(5)行,v 会依次成为u 的各个后继。如果在第(6)行发现u 按后序等于或先于v,就找到了后向弧u→v,并在第(7)行返回FALSE。如果没有找到这样的弧,就在第(9)行返回TRUE。
和之前一样,设n 是图G 中节点的数量,并设m 是节点数与弧数之间的较大者。我们已经知道在图9-36的第(1)行中对dfsForest的调用要花O(m)的时间。而第(5)到第(8)行是while循环的循环体,显然要花O(1)的时间。要得到while循环本身运行时间的良好边界,就必须用到我们在9.6节中为深度优先搜索的时间确定边界时用到的小诀窍。设mu 是节点u 的出度,那么第(4)行到第(8)行的循环就要进行mu 次。因此,第(4)行到第(8)行所花的时间是O(1+mu)。
第(3)行只要花O(1)的时间,因此第(2)行到第(8)行的for循环所花的时间是。正如在9.6节中验证过的,这些1的和是O(n),mu 的和则是m。由于n≤m,所以第(2)到第(8)行的
for循环的运行时间就是O(m)。正如深度优先搜索本身那样,检测环路的时间与查看整幅图所花的时间也只有常数因子的差别。
假设我们知道有向图G 是无环的。就像对任意图那样,可以为G 找到一个深度优先搜索森林,并为G 的节点确定后序编号。假设(v1,v2,…,vn)是图G 的节点按后序反向排列的表,也就是说v1是后序编号为n 的节点,v2的编号为n-1,而且一般而言,vi 是后序编号为n-i+1的节点。
该表中节点的次序具有这样的属性,G 中所有弧都是按照该次序向前行进的。要知道原因,假设vi →vj 是G 中的弧。因为G 是无环图,所以其中肯定不存在后向弧。因此,对每条弧而言,其头部按后序都是先于尾部的。也就是说,vj 按后序要先于vi 。不过表是与后序反向的,所以在表中vi 要先于vj 。也就是说,按照表的次序每条弧的尾部都要先于其头部。
具有图中每条弧的尾部都先于头部这种属性的图G 中,节点的次序叫作拓扑次序,而为这些节点找到这一次序的过程就叫作拓扑排序。只有无环图才有拓扑次序,而且正如我们已经看到的,通过深度优先搜索,可以在O(m)的时间内为无环图生成拓扑次序,其中m 是节点数和弧数之间的较大者。如果要为某节点给定后序编号,也就是要完成对该节点的dfs调用,我们会将该节点压入栈中。在完成所有调用后,该栈就成了节点按后序出现的表,其中编号最大的节点位于栈顶(前端)。这就是我们所需要的反向后序。因为深度优先搜索要花O(m)的时间,而且将节点压入栈只需要O(n)的时间,所以整个过程要花费O(m)的时间。
拓扑次序和环路查找的应用
本节中讨论的算法在不少情况下是很实用的。当执行用节点表示的特定任务所依照的次序有约束时,拓扑排序就会变得很方便。如果在执行任务v 之前必须执行u,就画一条从u到v的弧,然后拓扑次序就是我们执行所有任务所依照的次序。
非递归函数集合的调用图也是相似的例子,在这种情况下我们要在分析了某函数调用的函数之后再分析该函数。因为弧是从调用者到被调用函数的,所以拓扑次序的相反次序,也就是后序本身是我们分析函数所依照的次序,以确保我们只会在处理完某函数调用的函数后再来处理该函数。
在其他情况下,运行该环路测试也是有效的。例如,表示任务优先级的图中所含的环路就表示执行所有任务是没有次序可依照的,而调用图中的环路表示存在递归调用。
在图9-37a中有一幅无环图,而在图9-37b中是按照字母表次序考虑节点后得到的深度优先搜索森林。我们在图9-37b中还展示了从这次深度优先搜索中得到的后序编号。如果最先把后序编号最高的节点列出来,我们就得到拓扑次序(d,e,c,f,b,a)。读者应该自行验证一下图9-37a的8条弧中每条弧的尾部按照该表的次序都先于其头部。而这幅图恰好还有另外3种拓扑次序,比如(d,c,e,b,f,a)。
对于有向图可以提出一个很自然的问题:给定一个节点u,沿着有向图中的弧从u 可以到达哪些节点?我们将该节点集合称为节点u 的可达集。其实,如果对图中每个节点u 都询问这一可达性问题,就能知道对哪些节点对(u,v )而言存在从u 到v 的路径。
解决可达性问题的算法很简单。如果我们对节点u 感兴趣,就将所有节点标记为UNVISITED并调用dfs(u)。然后可以再次检测所有节点。那些标记上VISITED的节点就是从u 可达的节点,而其他节点则不是。如果想找到从另一个节点u 可达的节点,就将所有节点再次置为UNVISITED,并调用dfs(u)。我们可以为所有想要处理的节点重复该过程。
考虑图9-37a。如果从节点a 开始进行深度优先搜索,我们哪里都去不了,因为没有从a 发出的弧。因此,dfs(a)会立即终止。因为只有a 被访问过,所以可以得出结论,a 是从a 可达的唯一节点。
如果从b 开始,可以到达a,但这也就是全部了,所以b 的可达集就是{a,b }。同样,从c 开始可以到达{a,b,c,f },从d 则可以到达所有节点,从e 可以到达{a,b,e,f },而从f 只可以到达{a,f }。
再举个例子,考虑一下图9-26。从a 可以到达所有的节点。不过从除了a 之外的任意节点出发,可以到达除了a 之外的所有节点。

图 9-37 无环图的拓扑排序
服务热线
顶部
备案号: 苏ICP备11067224号
CopyRight © 2011 书生商友信息科技 All Right Reserved
24小时服务热线:400-111-6878 E-MAIL:1120768800@qq.com QQ:1120768800
网址: http://www.768800.com 网站建设:上往建站
关键词: 网站建设| 域名邮箱| 服务器空间| 网站推广| 上往建站| 网站制作| 网站设计| 域名注册| 网络营销| 网站维护|
企业邮箱| 虚拟主机| 网络建站| 网站服务| 网页设计| 网店美工设计| 网站定制| 企业建站| 网站设计制作| 网页制作公司|
400电话办理| 书生商友软件| 葬花网| 调温纤维| 海洋馆运营维护| 北京保安公司| 殡仪馆服务| 殡葬服务| 苏州殡葬一条龙| 朝阳殡葬| 苏州殡葬服务|
欢迎您免费咨询,请填写以下信息,我们收到后会尽快与您联系
服务热线:400-111-6878