算法导论22.1图的表示 练习总结
算法导论22.2广度优先搜索 练习总结
算法导论22.3深度优先搜索 练习总结
算法导论22.4拓扑排序 练习总结
算法导论22.5强连通分量 练习总结
22-1 (以广度优先搜索来对图的边进行分类)深度优先搜索将图中的边分类为树边、后向边、前向边和横向边。广度优先搜索也可以用来进行这种分类。具体来说,广度优先搜索将从源结点可以到达的边划分为同样的4种类型。
a.证明在对无向图进行的广度优先搜索中,下面的性质成立:
1.不存在后向边,也不存在前向边。
2.对于每条树边(u, v),我们有v.d = u.d + 1。
3.对于每条横向边(u, v),我么有v.d = u.d 或 v.d = u.d + 1。
b.证明在对有向图进行广度优先搜索时,下面的性质成立:
1.不存在前向边。
2.对于每条树边(u, v),我们有v.d = u.d + 1。
3.对于每条横向边(u, v),我们有v.d ≤ u.d + 1。
4.对于每条后向边(u, v),我们有0 ≤ v.d ≤ u.d。
ANSWER:
a:
b:
22-2 (衔接点、桥和双连通分量)设G=(V,E)为一个连通无向图。图G的衔接点是指图G中的一个结点,删除该结点将导致图不连通。图G的桥是指图中的一条边,删除该条边,图就不再连通。图G的双连通分量是指一个最大的边集合,里面的任意两条边都处于同一条简单环路中。设Gπ=(V,Eπ)为图G的深度优先树。
(事实上这里的双连通分量是点-双连通分量,还有边-双连通分量)
问题:
a. 证明:Gπ的根结点是图G的衔接点当且仅当它在Gπ中至少有两个子结点。
证明:
因为在对无向图G进行DFS时,每条边要么是树边,要么是后向边,因此当根结点删除时,如果它有两个以上的的子结点,这些子结点是无法相互到达的,因此根结点是图G的衔接点
b. 设结点v为Gπ的一个非根结点。证明:v是G的衔接点当且仅当结点v有一个子结点s,且没有任何从结点s或任何s的后代结点指向v的真祖先的后向边。
证明:
考虑v的任意子结点s,如果s及其后代不能连回v的真祖先,那么显然,删除v之后,v的真祖先与s不再连通。
反过来,如果s或它的后代存在一条后向边连回v的真祖先,则即使删了v,以s为根的子树都可以通过这条后向边与v的真祖先连通。
c. 定义:
v.low=min{u.d
w.d:(u,w)是结点v的某个后代结点u的一条后向边}
(d为第一时间戳)
请说明如何在O(E)的时间内为所有结点v计算出v.low的值
解:
对图G进行DFS,设现在遍历到结点u,初始化u.low=u.d。
接下来寻找拓展结点,设该结点为v.
如果结点v未被访问过,则我们从结点v处DFS以求得v.low,用其更新u.low
否则如果v不是u的父亲,那么我们用v.d更新u.low
d. 说明如何在O(E)时间内计算出图G的所有衔接点
解:
c中基本说的差不多了,以下是细节:
进行DFS时同时维护father,确保不把儿子到父亲的路径当成后向边。
不能边DFS边输出,因为可能多次满足条件,所以只能做上标记。
e. 证明:图G的一条边是桥当且仅当该边不属于G中的任何简单环路。
证明:
若存在一个桥属于G中的一个简单环路,那么删除这条边后,该桥的两端结点根据定义仍然可以通过其他路径连通,矛盾;而如果一条边不属于任何简单环路,那么这条边的两端节点只能通过这条边连通(否则会出现新环路),因此删除这条边时图G不再连通,故此时这条边是桥。
f. 说明如何在O(E)时间内计算出图G所有桥。
解:
过程其实与求衔接点很相似,但要注意判定过程中有更改:
当u.d>v.low时(u,v)是桥(可以发现等号不能成立)
g. 证明:G的双连通分量是G的非桥边的一个划分
证明:
事实上就是让你证双连通分量中删去任意一个点都不影响连通性。
这是一个双连通图显然的性质,不详细证了。
h. 给出一个O(E)时间复杂度的算法来给图G的每条边e做出标记。这个标记是一个正整数e.bcc且满足e.bcc=e’.bcc当且仅当边e和边e’在同一个双连通分量中。
解:
从森林的每个根结点开始DFS,用类似于求衔接点的方法维护每个结点的low值,但为了保存bcc,我们还要建一个栈来保存没有访问过的边;如果遍历的边为后向边,我们就用反向边更新自己(要注意反向边不能指向父亲)
附:边-双连通分量可先做一次DFS标记出所有的桥,然后第二次DFS找出边-双连通分量,因为边-双连通分量是没有公共结点的,所以第二次DFS保证不经过桥即可。
22-3(欧拉回路)欧拉回路的算法来自1873年的Hierholzer,前提是假设图G存在欧拉回路,即有向图任意点的出度和入度相同。从任意一个起始点v开始遍历,直到再次到达点v,即寻找一个环,这会保证一定可以到达点v,因为遍历到任意一个点u,由于其出度和入度相同,故u一定存在一条出边,所以一定可以到达v。将此环定义为C,如果环C中存在某个点x,其有出边不在环中,则继续以此点x开始遍历寻找环C’,将环C、C’连接起来也是一个大环,如此往复,直到图G中所有的边均已经添加到环中。
数据结构如下:
(1) 使用循环链表CList存储当前已经发现的环;
(2) 使用一个链表L保存当前环中还有出边的点;
(3) 使用邻接表存储图G
使用如下的步骤可以确保算法的复杂度为O(E):
(1) 将图G中所有点入L,取L的第一个结点
(2) 直接取其邻接表的第一条边,如此循环往复直到再次到达点v构成环C,此过程中将L中无出边的点删除。环C与环CList合并,只要将CList中的点v使用环C代替即可。
(3) 如果链表L为空表示欧拉回路过程结束,否则取L的第一个结点,继续步骤(2)
22-4 (可到达性)设G = (V, E)为一个有向图,且每个结点u∈V都标有一个唯一的整数值标记L(u),L(u)的取值为集合{1,2,…,|V| }。对于每个结点u∈V,设R(u) = {v∈V:u→v}为从结点u可以到达的所有结点的集合。定义min(u)为R(u)中标记最小的结点,即min(u)为结点v,满足L(v) = min{L(w):w∈R(u)}。请给出一个时间复杂度为O(V + E)的算法来计算所有结点u∈V的min(u)。
ANSWER:按照结点L(u)顺序对每个结点查找该结点可到达的结点,并找出最小的L(v),即min(u);
对V个结点进行查找共计E条边,所以时间复杂度为O(V + E)。