今天是憨批三人组的第一次旅行。半小时畅游田家炳楼~
本篇内容是从此还是怕天明的初代憨批拿出的一道题~
原题
CLRS 22.1-6:图的通用汇点(Universal Sink)
如果我们用邻接矩阵来存储图,那么绝大多数图算法的运行时间都是Ω(|V|²)(V为一个图的顶点集),但还是有些例外。比如,给定一个有向图G的邻接矩阵A,我们可以在Ο(|V|)时间内判断图G是否包含一个通用汇点,即一个入度为|V|-1出度为0的顶点。请给出这样的算法。
思路
-
第一反应
输入边的时候就统计出入度,然后顺序遍历一下结点的出入度,就ok惹(是的,如果是PAT考试的话肯定要先输入边集的,所以不能比Ο(|V|+|E|)复杂度更低了吧= =)…… -
然而,本题是说给定一个存了图的矩阵,用线性复杂度找出通用汇点。
-
标答
解释
![](https://img.haomeiwen.com/i10854666/5fe08a1e93c6596c.png)
-
初始: 矩阵G,N个结点编号1 - N,行下标i = 1,列下标j = 1
-
遍历,规则如下
- loop:检查G(i, j)
- 为1,Vi有出边。Vi不可能是通用汇点
i++(去检查V i+1,图上⬇️) - 为0,Vi没有指向Vj,Vi可能是通用汇点,而Vj不可能是
j++(继续检查Vi是不是指向了下一个点,图上➡️)
- 为1,Vi有出边。Vi不可能是通用汇点
- 终止:每步都⬇️或者➡️,i或者j必定超过N
- i超过N,不存在通用汇点,结束。
- j超过N,那Vi可能是通用汇点。然而,为什么Vk(k > i)不能是通用汇点呢?
因为j超过N,一定是已经向右走了N次,即在每一列都已经找到了0,而汇点x应该是除了G(x,x)为0外,x列全1的。此时循环是因为j爆掉而终止(最后一步是向右走),j一定大于i。k列(k>x)一定不是除G(k,k)外全1了,因为每列在前i行已经都有0了。
所以只要检查Vi的出入度,看它到底是不是通用汇点就可以了(通用汇点特征:若存在,必唯一。矩阵里的一个“十字”,交点为0,此外竖着全1,横着全0)。
- loop:检查G(i, j)
网友评论