第四章 图(五) - 《算法》读书笔记

第四章 图(五)

4.2.5 有向图中的强连通性

定义:如果两个顶点v和w是互相可达的,则称它们为强连通的,也就是说,既存在一条从v到w的有向路径,也存在一条从w到v的有向路径。如果一幅有向图中的任意两个顶点都是强连通的,则称这幅有向图也是强连通的。

  • 两个顶点时强连通的,当且仅当它们都在一个普通的有向环中

4.2.5.1 强连通分量

  • 作为一种等价关系,强连通性将所有顶点分为了一些等价类,每个等价类都是由相互均为强连通的顶点的最大子集组成的,我们称这些子集为强连通分量

4.2.5.4 Kosaraju算法

  • 在给定的一幅有向图G中,使用DepthFirstOrder(有向图中基于深度优先搜索的顶点排序)来计算它们的反向图GR的逆后序排列
  • 在G中进行标准的深度优先搜索,但是要按照刚才计算得到的顺序而非标准的顺序来访问所有未被标记的顶点
  • 在构造函数中,所有在同一个递归dfs()调用中被访问到的顶点,都在同一个强连通分量中,将它们按照和CC(无向图中的连通分量)相同的方式识别出来
public class KosarajuSCC{
    private boolean[] marked;
    private int[] id;
    private int count;
    
    public KosarajuSCC(Graph G){
        marked = new boolean[G.v()];
        id = new int[G.V()];
        DepthFirstOrder order = new DepthFirstOrder(G.reverse());
        for(int s : order.reversePost)
        	if(!marked[s]){
                dfs(G, s);
                count++;
            }
    }
    
    private void dfs(Graph G, int v){
        marked[v] = true;
        id[v] = count;
        for(int w: G.adj(v))
            if(!marked[w])
                dfs(G, w);
    }  
    public boolean stronglyConnected(int v, int w){
        return id[v] == id[w];
    }   
    public int id(int v){
        return id[v];
    }
    public int count(){
        return count;
    }
}
  • SCC的代码与CC仅有少量不同之处,主要区别在于,在反向图中按照逆后序进行搜索

使用深度优先搜索查找给定有向图G的反向图GR,根据由此得到的所有顶点的逆后序再次用深度优先搜索处理有向图G(Kosaraju算法),其构造函数中的每一次递归调用所标记的顶点都在同一个强连通分量之中。

Kosaraju算法的预处理所需的时间和空间与V+E成正比,且支持常数时间的有向图强连通性的查询。

4.2.5.4 再谈可达性

定义:有向图G的传递闭包是由相同的一组顶点组成的另一幅有向图,在传递闭包中存在一条从v指向w的边,当且仅当在G中w是从v可达的。

posted @ 2021-02-13 15:51  一天到晚睡觉的鱼  阅读(103)  评论(0)    收藏  举报