[学习笔记] Tarjan算法求强连通分量
今天,我们要探讨的就是——Tarjan算法。
Tarjan算法的主要作用便是求一张无向图中的强连通分量,并且用它缩点,把原本一个杂乱无章的有向图转化为一张DAG(有向无环图),以便解决之后的问题。
首先,我们在原图上跑一遍DFS,然后会发现三种边:
1、正常边:嗯,顾名思义就是连接祖先和儿子节点的边。
2、横叉边:连接到了已经弹出的节点的边(也能叫它小三边)。
3、返祖边:从儿子节点连到祖先的边。
那么通过进一步的观察我们可以发现:返祖边可能产生强连通分量,而横叉边不能。(如下图所示)
DFS遍历之后即为:
这时,我们发现上图出现了一种“大圈包小圈”的情况({1-5-6-8-9}和{5-6-8-5})那么我们应该如何处理才能做到当出现上图情况时只计算最大的那个强连通分量呢?
我们可以开两个数组:
dfn[i]:记录当遍历到节点i时是第几次dfs。
low[i]:记录以i为根的子树中能够连接到当前栈中最小的dfn值(也就是最上面的节点)。
然后每次取最小的low[i]就可以了。
Emmmmmmmmmmm,那就上代码吧。(Pascal党的福利哦)
var
vis:array[1..100000]of boolean;
stack,dfn,low,head,next,vet,blong,belong:array[1..100000]of longint;
tot,time,top,x,y,i,n,m,point:longint;
function min(a,b:longint):longint;
begin
if a<b then exit(a) else exit(b);
end;
procedure add(x,y:longint);
begin
inc(tot);
next[tot]:=head[x];
vet[tot]:=y;
head[x]:=tot;
end;
procedure tarjan(u:longint);
var
i,v:longint;
begin
inc(time);
dfn[u]:=time; low[u]:=time;
inc(top);
stack[top]:=u; vis[u]:=true;
i:=head[u];
while i<>0 do
begin
v:=vet[i];
if vis[v] then low[u]:=min(dfn[v],low[u])
else if dfn[v]=0 then
begin
tarjan(v);
low[u]:=min(low[v],low[u]);
end;
i:=next[i];
end;
if dfn[u]=low[u] then
begin
inc(point); belong[u]:=point;
while stack[top]<>u do
begin
belong[stack[top]]:=point;
vis[stack[top]]:=false;
dec(top);
end;
vis[u]:=false; dec(top)
end;
end;
procedure shrink_point;
var
u,i,v:longint;
begin
for u:=1 to n do
begin
i:=head[u];
while i<>0 do
begin
v:=vet[i];
if belong[i]<>belong[v] then add(belong[u],belong[v]);
i:=next[i];
end;
end;
end;
begin
read(n,m);
point:=n;
for i:=1 to m do
begin
read(x,y);
add(x,y);
end;
for i:=1 to n do
if dfn[i]=0 then tarjan(i);
shrink_point;
end.
[学习笔记] Tarjan算法求强连通分量的更多相关文章
- HDU 1269 迷宫城堡 tarjan算法求强连通分量
基础模板题,应用tarjan算法求有向图的强连通分量,tarjan在此处的实现方法为:使用栈储存已经访问过的点,当访问的点离开dfs的时候,判断这个点的low值是否等于它的出生日期dfn值,如果相等, ...
- Tarjan 算法求 LCA / Tarjan 算法求强连通分量
[时光蒸汽喵带你做专题]最近公共祖先 LCA (Lowest Common Ancestors)_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili tarjan LCA - YouTube Tarj ...
- [学习笔记] Tarjan算法求桥和割点
在之前的博客中我们已经介绍了如何用Tarjan算法求有向图中的强连通分量,而今天我们要谈的Tarjan求桥.割点,也是和上篇有博客有类似之处的. 关于桥和割点: 桥:在一个有向图中,如果删去一条边,而 ...
- 【算法】Tarjan算法求强连通分量
概念: 在有向图G中,如果两个定点u可以到达v,并且v也可以到达u,那么我们称这两个定点强连通. 如果有向图G的任意两个顶点都是强连通的,那么我们称G是一个强连通图. 一个有向图中的最大强连通子图,称 ...
- tarjan算法求强连通分量
先上代码: #include <iostream> #include <cstring> #include <vector> #include <stack& ...
- tarjan 算法求强连通分量
#include<bits/stdc++.h> #define ll long long using namespace std; const int P=1e6; ; ; const i ...
- Tarjan算法分解强连通分量(附详细参考文章)
Tarjan算法分解强连通分量 算法思路: 算法通过dfs遍历整个连通分量,并在遍历过程中给每个点打上两个记号:一个是时间戳,即首次访问到节点i的时刻,另一个是节点u的某一个祖先被访问的最早时刻. 时 ...
- kosaraju算法求强连通分量
什么是强连通分量?在这之前先定义一个强连通性(strong connectivity)的概念:有向图中,如果一个顶点s到t有一条路径,t到s也有一条路径,即s与t互相可达,那么我们说s与t是强连通的. ...
- Tarjan模板——求强连通分量
Tarjan求强连通分量的流程在这个博客讲的很清楚,再加上我也没理解透,这里就不写了. 缩点:将同一个连通块内的点视为同一个点. 扔一道模板题:codeVS2822爱在心中 第一问很显然就是求点数大于 ...
随机推荐
- Commando War (贪心)
Waiting for orders we held in the wood, word from the front never came By evening the sound of the g ...
- 免费获取 IntelliJ IDEA 激活码的 6 种方式!
你还在满世界找 IntelliJ IDEA 激活码? 破解的不稳定,也是违法的,有安全风险还不一定,不建议大家使用来历不明的补丁. 今天栈长就分享免费获取 IntelliJ IDEA 的 6 种方式, ...
- 自编Basic脚本 用BasicIntepreter执行 打印九九乘法表
源码下载:https://files.cnblogs.com/files/heyang78/BasicInterpreter2-20200601-2.rar 用编程语言打印九九乘法表不难,用自编解释器 ...
- Java 序列化界新贵 kryo 和熟悉的“老大哥”,就是 PowerJob 的序列化方案
本文适合有 Java 基础知识的人群 作者:HelloGitHub-Salieri HelloGitHub 推出的<讲解开源项目>系列. 项目地址: https://github.com/ ...
- Apache Jmter 压力测试教程
1.官网下载安装包,地址:http://jmeter.apache.org/download_jmeter. 2.下载得到解压包,双击解压. 3.点击/bin目录下面的jmeter.bat 启动软件 ...
- IDEA项目左侧目录看不到target
点击如下图所示图标,然后选择Show Excluded Files后即可出现
- python图片转码为base64
import base64 def image_base64(): with open(image_path, 'rb', )as f: base64_data = base64.b64encode( ...
- 超详细!盘点Python中字符串的常用操作
在Python中字符串的表达方式有四种 一对单引号 一对双引号 一对三个单引号 一对三个双引号 a = 'abc' b= "abc" c = '''abc''' d = " ...
- SSM框架中,事务无法回滚的原因和解决
原因: 由ServletContextListener加载spring配置文件产生的是父容器,springMVC产生的是子容器,子容器对Controller进行扫描装配时装配了@Service注解的实 ...
- k8s控制器资源
k8s控制器资源 Pod pod在之前说过,pod是kubernetes集群中是最小的调度单元,pod中可以运行多个容器,而node又可以包含多个pod,关系如下图: 在对pod的用法进行说明之前 ...