kosaraju算法用来求有向图的强连通分量

文章目录

  • 我们需要提前知道的知识
    • 什么是强连通
    • 强连通分量
    • 无向图的连通分量怎么计算
    • 什么是顶点的逆后序排列
    • 什么是反向图
  • kosaraju算法
  • 对于该算法的理解
  • 无向图,有向图的图结构

我们需要提前知道的知识

什么是强连通

有向图中,从v可以到达w, 从w也可以到达v,那么称v和w是强连通的
如果一副图中任意两点强连通,这幅图也是强连通的。


强连通分量

  1. 本图强连通分量为3
  2. 本图强连通分量为4
  3. 本图强连通分量为4

无向图的连通分量怎么计算

kosaraju算法不过是在下面的基础上增加了几行,

package Algorithm;public class CC {private int count;//连通分量个数private boolean[] marked;//标记是否访问过private int[] id;//id[v]=1,说明顶点v在分量1里面public CC(Graph g){marked=new boolean[g.V()];id=new int[g.V()];for (int i = 0; i <g.V(); i++) {if(!marked[i]){dfs(g,i);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 connected(int v,int w){return id[v]==id[w];}public int count(){return count;}public int id(int v){return id[v];}
}

什么是顶点的逆后序排列

调用dfs时,将顶点放在栈里面即可。

package Algorithm.DirectedGraph;
import java.util.LinkedList;
public class DF_Order {private LinkedList<Integer>  reversePost;//栈private boolean[] marked;//标记是否访问过private int vNum;//顶点数目public DF_Order(DiGraph g){vNum=g.getV();reversePost=new LinkedList<>();marked=new boolean[g.getV()];for (int i = 0; i < g.getV(); i++) {if(!marked[i]){dfs(g,i);}}}private void dfs(DiGraph g, int i) {marked[i]=true;for(int w:g.adj(i)){if(!marked[w]){dfs(g,w);}}reversePost.push(i);}public Iterable<Integer> reversePost(){return reversePost;}
}

什么是反向图

将有向图的边的指向反过来即可。

反向图:


kosaraju算法

步骤

  1. 将图反向
  2. 得到反向图的逆后序排列
  3. 用逆后序的顺序遍历原图
package Algorithm.DirectedGraph;public class KosarajuCC {private int[] id;private int count;private boolean[] marked;public KosarajuCC(DiGraph graph){marked=new boolean[graph.getV()];id=new int[graph.getV()];DF_Order order = new DF_Order(graph.reverse());for (int x:order.reversePost()){if(!marked[x]) {dfs(graph,x);count++;}}}private void dfs(DiGraph graph, int v) {marked[v]=true;id[v]=count;for (int x:graph.adj(v)){if(!marked[x]) dfs(graph,x);}}public boolean stronglyConnected(int v,int w){return id[v]==id[w];}public int getCount(){return count;}}

对于该算法的理解

我们从哪一个顶点进行DFS呢?
按照顶点顺序:0 1 2 3 4 5
那么0 1是一个强连通分量
2 3 4 5是一个强连通分量,显然是不对的。
按照逆后序就是: 0 1 4 5 2 3
那么0 1是一个强连通分量
4 5是一个强连通分量
2 3是一个强连通分量
先访问0 1 4 5,在进行2 3,那么2通向1或4 的道路被封死了。

用这个反向图的逆后序去深度优先搜索(正向)图,可以发现每次递归都是在同一个强连通分量之中。

  1. 如图

    逆后序得到:0 1 4 5 2 3

  2. .

    逆后序得到 4 5 2 3 0 1

  3. .

    逆后序得到 2 3 0 1 4 5


无向图,有向图的图结构

package Algorithm.DirectedGraph;import Algorithm.Bag;public class DiGraph {private int v;private int e;private Bag<Integer>[] adj;public DiGraph(int v,int e){this.v=v;this.e=e;adj=(Bag<Integer>[]) new Bag[v];for (int i = 0; i < v; i++) {adj[i]=new Bag<Integer>();}}public DiGraph(int v){this.v=v;adj=(Bag<Integer>[]) new Bag[v];for (int i = 0; i < v; i++) {adj[i]=new Bag<Integer>();}}public int getV(){return v;};public int getE(){return e;};public void add(int v,int w){adj[v].add(w);}public Iterable<Integer> adj(int v){return adj[v];}public DiGraph reverse(){DiGraph diGraph = new DiGraph(v);for (int i = 0; i < v; i++) {for (int x:adj(i)){diGraph.add(x,i);}}return diGraph;}
}
//无向图
package Algorithm;
public class Graph {private int V;private int E;private Bag<Integer>[] adj;//邻接表public Graph(int v,int e) {this.V = v;this.E=e;adj=(Bag<Integer>[]) new Bag[v];for (int i = 0; i < V; i++) {adj[i]=new Bag<Integer>();}}public Graph(int v){this.V=v;adj=(Bag<Integer>[]) new Bag[v];for (int i = 0; i < v; i++) {adj[i]=new Bag<Integer>();}}public int V(){//返回定点数return V;}public int E(){//返回边数return E;}public void addEdge(int v,int w){//添加一条边adj[v].add(w);adj[w].add(v);E++;}public Iterable<Integer> adj(int v){//和v相邻的所有顶点。只是输入的时候,不包含计算得出的所有return adj[v];}
}
package Algorithm;import java.util.Iterator;public class Bag<Item> implements Iterable<Item> {@Overridepublic Iterator<Item> iterator() {//实现iterable,才可以foreach//iterator 迭代器return new ListIterator();}private class ListIterator implements Iterator<Item> {private node current=first;@Overridepublic boolean hasNext() {return current!=null;}@Overridepublic Item next() {Item item=current.val;current=current.next;return item;}}private class node{Item val;node next;}private int n=0;private  node first;public void add(Item item){node oldfirst=first;first=new node();first.val=item;first.next=oldfirst;n++;}public boolean isEmpty(){return first==null;}public int size(){return n;}
}

参考自:

  1. 知乎:https://www.zhihu.com/question/58926821
  2. 算法第四版(橙色)

kosaraju算法相关推荐

  1. HDU4635(强连通分量+Kosaraju算法)

    题意:给出一个有向图,最多添加多少条边使这个图依然不是强连通图:当这个图是强连通图时,输出-1: 求解思路:强连通分量求解: 强连通图:在有向图中,任意节点除法都可以到达其余所有节点,则称为强连通图. ...

  2. HDU3072(Kosaraju算法)

    题意:给出一个有向图,并且给出从X->Y之间的权值(也是cost),要求出强连通分量之间的最小边权,最后将求出的强连通分量之间的权值相加. Kosaraju算法: 算法思路: 步骤1:对正向图( ...

  3. HDU2767(强连通分量+Kosaraju算法)

    题意:需要加多少边才能把一个图变成强连通分量 强连通图:在有向图中,任意节点除法都可以到达其余所有节点,则称为强连通图. 强连通分量:在非强连通图的有向图中,选取部分点为强连通图,该强连通子图称为强连 ...

  4. Kosaraju 算法检测有向图的强连通性

    给定一个有向图 G = (V, E) ,对于任意一对顶点 u 和 v,有 u --> v 和 v --> u,亦即,顶点 u 和 v 是互相可达的,则说明该图 G 是强连通的(Strong ...

  5. Kosaraju 算法查找强连通分支

    有向图 G = (V, E) 的一个强连通分支(SCC:Strongly Connected Components)是一个最大的顶点集合 C,C 是 V 的子集,对于 C 中的每一对顶点 u 和 v, ...

  6. Kosaraju算法、Tarjan算法分析及证明--强连通分量的线性算法

    一.背景介绍 强连通分量是有向图中的一个子图,在该子图中,所有的节点都可以沿着某条路径访问其他节点.强连通性是一种非常重要的等价抽象,因为它满足 自反性:顶点V和它本身是强连通的 对称性:如果顶点V和 ...

  7. Kosaraju算法(发现强连通分图算法)

    看论文的时候,看到Kosaraju算法.Kosaraju是一个强连通分图的发现算法,如有代码中有详细的注释,所以就不赘述了.直接上码(使用webgraph库实现,在我之前的文章中,对webgraph有 ...

  8. 有向图最长路径算法_算法数据结构 | 三个步骤完成强连通分量分解的Kosaraju算法...

    强连通分量分解的Kosaraju算法 今天是算法数据结构专题的第35篇文章,我们来聊聊图论当中的强连通分量分解的Tarjan算法. Kosaraju算法一看这个名字很奇怪就可以猜到它也是一个根据人名起 ...

  9. 图论 —— 图的连通性 —— Kosaraju 算法

    [概述] Kosaraju 算法是最容易理解,最通用的求强连通分量的算法,其关键的部分是同时应用了原图 G 和反图 GT . [基本思想] 1.对原图 G 进行 DFS 搜索,计算出各顶点完成搜索的时 ...

最新文章

  1. 如何用 Python 和 Flask 建立部署一个 Facebook Messenger 机器人
  2. 15行用Python实现仿百度搜索引擎
  3. [bzoj1500 维修数列](NOI2005) (splay)
  4. 深入理解BodyTagSupport,包括SKIP_PAGE, EVAL_PAGE等
  5. webpack4搭建vue
  6. django进阶03静态文件和模板
  7. objective-c 汇编语言,Objective-C和C的区别?
  8. mysql服务启动失败
  9. WPS中JS宏简单运用
  10. 从pvlib入门光伏发电系统
  11. 常用智能小车电机驱动模块选型
  12. P1359 租用游艇 dfs/dp/floyd/dijk/spfa DAG(有向无环图)
  13. js 将图片置灰_将图片转换成黑白(灰色)的css和js的方法
  14. 微信接口昵称在服务器乱码,微信网页开发获取用户昵称乱码 微信昵称包含emoji表情乱码的解决方案...
  15. dell服务器新bois系统设置u盘启动,跟大家讲讲dell新版biosU盘启动顺序
  16. Wireshark数据包分析——Teardrop泪滴攻击
  17. 为什么onenote一直在加载_用OneNote打造全平台的数字笔记本
  18. VS2005的数据断点功能
  19. Spring框架--SpringMVC文件上床
  20. 演讲实录丨祖昆仑 VR一体机是过渡产品形态么?

热门文章

  1. 基础知识——列表简介(二)
  2. Layui Excle/csv数据导出
  3. laravel 如何自定义全局的方法/类
  4. Android Gradle 笔记
  5. 15.知识产权与标准化
  6. Hive的“rowid”
  7. React 组件之间 事件调用(父组件调用子组件)
  8. HSQLDB安装与使用
  9. linux apache 手动安装教程,linux下手动安装apache
  10. android流量控制的实现,Android系统中P2P应用数据包捕获及流量控制研究