当前位置:网站首页>有向图的强连通分量
有向图的强连通分量
2022-07-03 00:35:00 【chengqiuming】
一 算法步骤
1 深度优先遍历节点,在第一次访问节点x时,将 x 入栈,且 dfn[x]=low[x]=++num
2 遍历 x 的所有邻接点y。
若 y 没被访问,则递归访问 y,返回时更新 low[x]=min(low[x],low[y])
若 y 已被访问且在栈中,则令 low[x]=min(low[x],dfn[y])
3 在x回溯之前,如果判断 low[x]=dfn[x],则从栈中不断弹出节点,直到 x 出栈时停止。弹出的节点就是一个连通分量。
二 举例
1 从节点 1 出发进行深度优先搜索,dfn[1]=low[1]=1,1入栈;
2 遍历1的所有邻接点
2 没有被访问,递归访问 2,2 入栈,返回时,更新 dfn[2]=low[2]=2。
3 回溯时,因为 dfn[2]=low[2],2 出栈,得到强连通分量2。

4 回溯到 1 后,继续访问1的下一个邻接点3,接着访问 3-4-5,5 的邻接点 1 的已经访问,且 1 在栈中,更新low[5]=min(low[5],dfn[1])=1,回溯时更新 low[4]=min(low[4],low[5])=1, low[3]=min(low[3],low[4])=1,low[1]=min(low[1],low[3])=1.节点 1 的所有邻接点都已访问完毕,因为 dfn[1]=low[1],所以开始出栈,直到遇到1,得到强连通分量 5 4 2 1。

三 代码
package graph.tarjanscc;
import java.util.Scanner;
import java.util.Stack;
public class TarjanSCC {
static final int maxn = 1000 + 5;
static int n;
static int m;
static int head[];
static int cnt;
static int root;
static int low[];
static int dfn[];
static int num;
static Edge e[] = new Edge[maxn << 1];
static Stack<Integer> s = new Stack<>();
static boolean ins[] = new boolean[maxn];
static {
for (int i = 0; i < e.length; i++) {
e[i] = new Edge();
}
}
static void add(int u, int v) { // 添加一条边u--v
e[++cnt].next = head[u];
e[cnt].to = v;
head[u] = cnt;
}
static void tarjan(int u) { // 求强连通分量
low[u] = dfn[u] = ++num;
System.out.println("low[" + "]=" + low[u] + "\tdfn[" + u + "]=" + dfn[u]);
ins[u] = true;
s.push(u);
for (int i = head[u]; i != 0; i = e[i].next) {
int v = e[i].to;
if (dfn[v] == 0) {
tarjan(v);
low[u] = Math.min(low[u], low[v]);
System.out.println("update1:low[" + u + "]=" + low[u]);
} else if (ins[v]) {
low[u] = Math.min(low[u], dfn[v]);
System.out.println("update2:low[" + u + "]=" + low[u]);
}
}
if (low[u] == dfn[u]) {
int v;
System.out.println("强连通分量:");
do {
v = s.peek();
s.pop();
System.out.print(v + " ");
ins[v] = false;
} while (v != u);
System.out.println();
}
}
static void init() {
head = new int[maxn];
low = new int[maxn];
dfn = new int[maxn];
ins = new boolean[maxn];
cnt = num = 0;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
n = scanner.nextInt();
m = scanner.nextInt();
init();
int u, v;
while (m-- > 0) {
u = scanner.nextInt();
v = scanner.nextInt();
add(u, v);
}
for (int i = 1; i <= n; i++)
if (dfn[i] == 0) {
tarjan(i);
}
}
}
class Edge {
int to;
int next;
}四 测试
绿色为输入,白色为输出。

边栏推荐
- Sentry developer contribution Guide - configure pycharm
- [AUTOSAR VI description document]
- [AUTOSAR + IO Architecture]
- 飞凌搭载TI AM62x的ARM核心板/开发板首发上市,亮相Embedded World 2022
- Understanding and distinguishing of some noun concepts in adjustment / filtering
- Problèmes de configuration lex & yacc & Bison & Flex
- 线程的启动与优先级
- 瑞萨RZ/G2L 处理器简介|框架图|功耗|原理图及硬件设计指南
- Win10 can't be installed in many ways Problems with NET3.5
- 【AutoSAR 五 方法论】
猜你喜欢

Understanding and distinguishing of some noun concepts in adjustment / filtering

图解网络:什么是虚拟路由器冗余协议 VRRP?

1.11 - bus
[AUTOSAR five methodology]

瑞萨RZ/G2L ARM开发板存储读写速度与网络实测

In the first half of 2022, there are 10 worth seeing, and each sentence can bring you strength!

AEM: Nanlin fan Ben et al. - plant rhizosphere growth promoting bacteria control soybean blight

Web2.0的巨头纷纷布局VC,Tiger DAO VC或成抵达Web3捷径

What is needed to develop a domestic arm intelligent edge computing gateway

【AutoSAR 十 IO架构】
随机推荐
【AutoSAR 十一 通信相关机制】
File operation io-part2
这不平凡的两年,感谢我们一直在一起!
lex && yacc && bison && flex 配置的問題
Foundations of data science is free to download
递归处理组织的几种情况
Leetcode-934: the shortest Bridge
12_微信小程序之微信视频号滚动自动播放视频效果实现
百度智能云牵头打造智能云综合标准化平台
Vulkan-性能及精细化
Extension of flutter
Tensorflow 2.x(keras)源码详解之第十五章:迁移学习与微调
The arm core board / development board of Feiling equipped with Ti am62x made its debut in embedded world 2022
Nacos+openfeign error reporting solution
数组与集合性能比较
lex && yacc && bison && flex 配置的问题
What is needed to develop a domestic arm intelligent edge computing gateway
KingbaseES ALTER TABLE 中 USING 子句的用法
[shutter] image component (load network pictures | load static pictures | load local pictures | path | provider plug-in)
指针初阶(基础)