图 | 通用汇点 Universal Sink

今天是憨批三人组的第一次旅行。半小时畅游田家炳楼~
本篇内容是从此还是怕天明的初代憨批拿出的一道题~

原题

CLRS 22.1-6:图的通用汇点(Universal Sink)

如果我们用邻接矩阵来存储图,那么绝大多数图算法的运行时间都是Ω(|V|²)(V为一个图的顶点集),但还是有些例外。比如,给定一个有向图G的邻接矩阵A,我们可以在Ο(|V|)时间内判断图G是否包含一个通用汇点,即一个入度为|V|-1出度为0的顶点。请给出这样的算法。

思路

  • 第一反应
    输入边的时候就统计出入度,然后顺序遍历一下结点的出入度,就ok惹(是的,如果是PAT考试的话肯定要先输入边集的,所以不能比Ο(|V|+|E|)复杂度更低了吧= =)……

  • 然而,本题是说给定一个存了图的矩阵,用线性复杂度找出通用汇点。

  • 标答

解释
在矩阵里遍历的示意图
  • 初始: 矩阵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是不是指向了下一个点,图上➡️)
    • 终止:每步都⬇️或者➡️,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)。

你可能感兴趣的:(图 | 通用汇点 Universal Sink)