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算法的更多相关文章

  1. 算法笔记_144:有向图强连通分量的Tarjan算法(Java)

    目录 1 问题描述 2 解决方案 1 问题描述 引用自百度百科: 如果两个顶点可以相互通达,则称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连 ...

  2. 有向图强连通分量的Tarjan算法

    有向图强连通分量的Tarjan算法 [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G ...

  3. 【转】有向图强连通分量的Tarjan算法

    原文地址:https://www.byvoid.com/blog/scc-tarjan/ [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly con ...

  4. 【转载】有向图强连通分量的Tarjan算法

    转载地址:https://www.byvoid.com/blog/scc-tarjan [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly conn ...

  5. 有向图强连通分量的Tarjan算法(转)

    [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极 ...

  6. 『图论』有向图强连通分量的Tarjan算法

    在图论中,一个有向图被成为是强连通的(strongly connected)当且仅当每一对不相同结点u和v间既存在从u到v的路径也存在从v到u的路径.有向图的极大强连通子图(这里指点数极大)被称为强连 ...

  7. 有向图强连通分量的Tarjan算法及模板

    [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强联通(strongly connected),如果有向图G的每两个顶点都强联通,称有向图G是一个强联通图.非强联通图有向 ...

  8. 强连通分量的Tarjan算法

    资料参考 Tarjan算法寻找有向图的强连通分量 基于强联通的tarjan算法详解 有向图强连通分量的Tarjan算法 处理SCC(强连通分量问题)的Tarjan算法 强连通分量的三种算法分析 Tar ...

  9. 有向图强连通分量的Tarjan算法和Kosaraju算法

    [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极 ...

随机推荐

  1. 🏃‍♀️点亮你的Vue技术栈,万字Nuxt.js实践笔记来了~

    前言 作为一位 Vuer(vue开发者),如果还不会这个框架,那么你的 Vue 技术栈还没被点亮. Nuxt.js 是什么 Nuxt.js 官方介绍: Nuxt.js 是一个基于 Vue.js 的通用 ...

  2. RunLoop总结

    参考学习了YY大神的http://blog.ibireme.com/2015/05/18/runloop/#mode RunLoop: 看做是一个对象,这个对象管理了其需要处理的事件和消息,并提供了一 ...

  3. P2756 飞行员配对方案问题 网络流

    P2756 飞行员配对方案问题 #include <bits/stdc++.h> using namespace std; , inf = 0x3f3f3f; struct Edge { ...

  4. 3.9 Go Slice切片

    3.9 Go Slice切片 Go语言切片(Slice) 切片是可动态变化的序列,是对数组的引用,引用类型,遵循引用传递的机制 slice类型写作[ ]T,T是slice元素类型,var s1 []i ...

  5. 使用urllib

    urlopen的基本用法: 工具为:python3(windows) 其完整表达式为: urllib.request.urlopen(url, data=None, [timeout, ]*, caf ...

  6. Python 如何随机打乱列表(List)排序

    场景: 现在有一个list:[1,2,3,4,5,6],我需要把这个list在输出的时候,是以一种随机打乱的形式输出. 专业点的术语:将一个容器中的数据每次随机逐个遍历一遍. 注意:不是生成一个随机的 ...

  7. deno+mongo实战踩坑记

    自从 deno 1.0 发布以来,有关 deno 的文章很多,大多数都是在讨论怎么安装 deno .deno 有哪些特点 .deno 和 node 有哪些异同.deno是不是 node 的替代品等.咱 ...

  8. npm run build 时 报 __webpack_public_path__ = window.webpackPublicPath; 中的windows未定义

    原本 webpack.js在webpack.config.babel.js同目录下,在app.jsx中引用,用mac打包没问题,但是window就报window未定义,改到src和app.jsx同目录 ...

  9. 基于 abp vNext 和 .NET Core 开发博客项目 - 异常处理和日志记录

    在开始之前,我们实现一个之前的遗留问题,这个问题是有人在GitHub Issues(https://github.com/Meowv/Blog/issues/8)上提出来的,就是当我们对Swagger ...

  10. ASP.NET Core on K8S学习之旅(14)Ingress灰度发布

    本篇已加入<.NET Core on K8S学习实践系列文章索引>,可以点击查看更多容器化技术相关系列文章. 之前一篇介绍了Ingress的基本概念和Nginx Ingress的基本配置和 ...