[学习笔记] 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爱在心中 第一问很显然就是求点数大于 ...
随机推荐
- [BUUOJ记录] [ACTF2020 新生赛]Include
本题主要考查了利用php://filter伪协议进行文件包含 进入题目根据Tip进入正题,可以看到URL中存在文件包含(题目名也很直接) 首先考虑 "php://input"伪协议 ...
- 06_Python异常处理机制
1.异常概述 1.什么是错误: 错误是指有逻辑或语法等导致一个程序无法正常执行的问题 2.什么是异常: 异常时程序出错时标识的一种状态,程序不会向下执行而转去调用此函数的地方等待处理错误并恢复 ...
- python3之print()函数
print语法格式 print()函数具有丰富的功能,详细语法格式如下: print(value, -, sep=' ', end='\n', file=sys.stdout, flush=False ...
- 启动Tomcat服务器端口被占用解决方法
Caused by: java.net.BindException: Address already in use: bind 1.输入 netstat -ano|findstr 8080,回车,显示 ...
- 面试官问我:看过sharding-jdbc的源码吗?我吧啦吧啦说了一通!!
写在前面 在产品初期快速迭代的过程中,往往为了快速上线而占据市场,在后端开发的过程中往往不会过多的考虑分布式和微服务,往往会将后端服务做成一个单体应用,而数据库也是一样,最初会把所有的业务数据都放到一 ...
- IDEA下Git分支开发
IDEA下Git分支开发使用 1.新建本地开发分支 VCS-->git-->branches-->New Branch,输入分支名字,如branch_test,点击OK后本地开发分支 ...
- Flash 0day(CVE-2018-4878)复现过程
一.前言介绍 2018年2月1号,Adobe官方发布安全通报(APSA18-01),声明Adobe Flash 28.0.0.137及其之前的版本,存在高危漏洞(CVE-2018-4878). 从Ad ...
- 乔悟空-CTF-i春秋-Web-Not Found-🙋🏻♂️
2020.09.08 又是匆匆忙忙的一天- 做题 题目 题目地址 做题 做题??做个屁,啥也不知道,干瞪眼
- [LeetCode]301. 删除无效的括号(DFS)
题目 题解 step1. 遍历一遍,维护left.right计数器,分别记录不合法的左括号.右括号数量. 判断不合法的方法? left维护未匹配左括号数量(增,减)(当left为0遇到右括号,则交由r ...
- windows下nginx的配置
这里做的nginx的配置主要的功能是: 能够用localhost访问本地文件夹中的项目 输入ip地址访问本地文件夹中的项目 反向代理其他地址访问本地文件 1.nginx安装地址 2.解压之后的文件如下 ...