Java实现有向图强连通分量的Tarjan算法
1 问题描述
引用自百度百科:
如果两个顶点可以相互通达,则称两个顶点强连通(strongly connected)。如果有向图G的每两个顶点都强连通,称G是一个强连通图。有向图的极大强连通子图,称为强连通分量(strongly connected components)。
Tarjan算法是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树。搜索时,把当前搜索树中未处理的节点加入一个堆栈,回溯时可以判断栈顶到栈中的节点是否为一个强连通分量。
定义DFN(u)为节点u搜索的次序编号(时间戳),Low(u)为u或u的子树能够追溯到的最早的栈中节点的次序号。
当DFN(u)=Low(u)时,以u为根的搜索子树上所有节点是一个强连通分量。
2 解决方案
下面代码所使用图:

package com.liuzhen.practice;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.Stack;
public class Main {
public static int MAX = 100;
public static int count; //用于对图中顶点遍历的次序进行计数
public static int n;
public static int[] DFN = new int[MAX]; //记录图中每个节点的DFS遍历的时间戳(即次序)
public static int[] Low = new int[MAX]; //记录每个顶点的所在树的根节点编号
public static boolean[] inStack = new boolean[MAX]; //用于记录当前节点是否在栈中
public static Stack<Integer> stack;
public void init(int n) {
count = 0;
stack = new Stack<Integer>();
for(int i = 0;i <= n;i++) {
DFN[i] = -1; //代表顶点i未被遍历
Low[i] = -1;
inStack[i] = false;
}
}
static class edge {
public int a; //边的起点
public int b; //边的终点
edge(int a, int b) {
this.a = a;
this.b = b;
}
}
public void dfs(ArrayList<edge>[] map, int start) {
DFN[start] = count++;
Low[start] = DFN[start];
stack.push(start);
inStack[start] = true;
int j = start;
for(int i = 0;i < map[start].size();i++) {
j = map[start].get(i).b;
if(DFN[j] == -1) { //顶点j未被遍历
dfs(map, j);
Low[start] = Math.min(Low[start], Low[j]);
} else if(inStack[j]) {
Low[start] = Math.min(Low[start], DFN[j]);
}
}
if(DFN[start] == Low[start]) {
System.out.print("强连通分量:");
do {
j = stack.pop();
System.out.print(j+" ");
inStack[j] = false;
} while(start != j);
System.out.println();
}
return;
}
public static void main(String[] args) {
Main test = new Main();
Scanner in = new Scanner(System.in);
n = in.nextInt();
test.init(n);
int k = in.nextInt(); //有向图的边数目
@SuppressWarnings("unchecked")
ArrayList<edge>[] map = new ArrayList[n + 1];
for(int i = 0;i <= n;i++)
map[i] = new ArrayList<edge>();
in.nextLine();
for(int i = 0;i < k;i++) {
int a = in.nextInt();
int b = in.nextInt();
map[a].add(new edge(a, b));
}
test.dfs(map, 1);
}
}
运行结果:
8
2
3
4
4
5
1
6
6
强连通分量:6
强连通分量:5
强连通分量:3 4 2 1
Java实现有向图强连通分量的Tarjan算法的更多相关文章
- 算法笔记_144:有向图强连通分量的Tarjan算法(Java)
目录 1 问题描述 2 解决方案 1 问题描述 引用自百度百科: 如果两个顶点可以相互通达,则称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连 ...
- 有向图强连通分量的Tarjan算法
有向图强连通分量的Tarjan算法 [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G ...
- 【转】有向图强连通分量的Tarjan算法
原文地址:https://www.byvoid.com/blog/scc-tarjan/ [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly con ...
- 【转载】有向图强连通分量的Tarjan算法
转载地址:https://www.byvoid.com/blog/scc-tarjan [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly conn ...
- 有向图强连通分量的Tarjan算法(转)
[有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极 ...
- 『图论』有向图强连通分量的Tarjan算法
在图论中,一个有向图被成为是强连通的(strongly connected)当且仅当每一对不相同结点u和v间既存在从u到v的路径也存在从v到u的路径.有向图的极大强连通子图(这里指点数极大)被称为强连 ...
- 有向图强连通分量的Tarjan算法及模板
[有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强联通(strongly connected),如果有向图G的每两个顶点都强联通,称有向图G是一个强联通图.非强联通图有向 ...
- 强连通分量的Tarjan算法
资料参考 Tarjan算法寻找有向图的强连通分量 基于强联通的tarjan算法详解 有向图强连通分量的Tarjan算法 处理SCC(强连通分量问题)的Tarjan算法 强连通分量的三种算法分析 Tar ...
- 有向图强连通分量的Tarjan算法和Kosaraju算法
[有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极 ...
随机推荐
- 世界这么大,Python 也想去看看
把时间线拉回到 2015 年 4 月 13 日,一位河南省实验中学的心里老师在辞职信上写下了「世界那么大,我想去看看」这句话,后来爆红网络,我想这位心里老师当时写这句话的时候肯定没想到这句只有十个字的 ...
- gather函数
gather(input, dim, index):根据 index,在 dim 维度上选取数据,输出的 size 与 index 一致 # input (Tensor) – 源张量 # ...
- dedecms织梦建站后怎么防止被黑,加强安全漏洞措施?
dedecms织梦建站后怎么防止被黑,加强安全漏洞措施? 很多人反映dedecms织梦网站被黑的情况,因为织梦相对来说漏洞还是挺多的,特别是新建设的站点,有些目录.文件该删的删,权限及安全都要设置,以 ...
- java - >IO流_缓冲流(高效流)
缓冲流(高效流) 在我们学习字节流与字符流的时候,大家都进行过读取文件中数据的操作,读取数据量大的文件时,读取的速度会很慢,很影响我们程序的效率,那么,我想提高速度,怎么办? Java中提高了一套缓冲 ...
- redis主从复制、主从延迟知几何
本片章节主要从 redis 主从复制延迟相关知识及影响因素做简要论述. 1.配置:repl-disable-tcp-nodelay 也即是TCP 的 TCP_NODELAY 属性,决定数据的发送时机. ...
- [Unity UGUI序列帧]简单实现序列帧的播放
在使用序列帧之前需要准备好序列帧的图集,打图集的操作参考 [Unity UGUI图集系统]浅谈UGUI图集使用 准备好序列帧图集,序列帧的播放原理就是获取到图集中的所有图片,然后按照设置的速度按个赋值 ...
- zabbix 自定义指标数据来源
1.cpu load https://blog.csdn.net/scugxl/article/details/77199403 1)基本含义:运行队列长度,表示当前有多少个正在等待的进程和正在执行的 ...
- unity-消息的注册,监听,回调
最近在空闲时间准备做个小游戏,先把一些基本框架搭建好,本次记录的是消息的注册,监听和回调等 其实这些就是基于C#的委托(delegate) 第一步:定义一些委托 namespace Common.Me ...
- 201771010128王玉兰《面向对象程序设计(Java)》第八周学习总结
第一部分:理论知识部分总结 (1)接口:接口不是类,而是对类胡一组需求描述,由常量肯一组抽象方法组成. a:接口中不包括变量和有具体实现的方法 b:只要类实现了接口,则该类要遵从接口描述的统 一格式进 ...
- .Net基础之4——流程控制
(1)异常捕获 我们在程序中经常会出现各种各样的异常,你如果想要你的程序变得坚强一点. 在你的代码中应该经常性的使用try-catch来进行异常捕获. 语法: try { 可能会出现异常的代码: } ...