萌新学习图的强连通(Tarjan算法)笔记
--主要摘自北京大学暑期课《ACM/ICPC竞赛训练》
在有向图G中,如果任意两个不同顶点相互可达,则称该有向图是强连通的;
有向图G的极大强连通子图称为G的强连通分支;
Tarjan算法:
做一遍DFS,
Dfn[ i ] 表示节点i 在DFS过程中的访问序号(也可以叫做开始时间)。
Low[ i ]表示从i 节点出发DFS过程中i 下方节点(可以说是开始时间大于dfn[ i ],且由i 可达的节点;也可以说是与i邻接的未删除的顶点)所能到达的最早的节点的开始时间。
DFS过程中,碰到哪个节点,就将哪个节点入栈。栈中节 点只有在其所属的强连通分量已经全部求出时,才会出栈。
如果发现某节点u有边连到栈里的节点v,则更新u的low 值为min(low[u],dfn[v]) ,若low[u]被更新为dfn[v],则表明目前 发现u可达的最早的节点是v.
对于u的子节点v,从v出发进行的DFS结束回到u 时,使得 low[u] = min(low[u],low[v])。因为u可达v, 所以v可达的最早的节点,也是u可达的。
如果一个节点u,从其出发进行的DFS已经全部完 成并回到u,而且此时其low值等于dfn值,则说明 u可达的所有节点,都不能到达任何比u早的节点 --- 那么该节点u就是一个强连通分量在DFS搜索树 中的根。
此时,显然栈中u上方的节点,都是不能到达比u 早的节点的。将栈中节点弹出,一直弹到u(包括u), 弹出的节点就构成了一个强连通分量.
在DFS过程中会形成一棵搜索树,在搜索树上越先遍历到的节点,显然dfn的值就 越小。dfn值越小的节点,就称为越“早”。
模拟一发:
顶点 |
Dfn |
low |
栈 |
强连通分量 |
a |
1 |
1 |
a |
|
b |
2 |
2 |
b,a |
|
c |
3 |
3 |
c,b,a |
|
e |
4 |
4 |
e,c,b,a=>e的low[i]==dfn[i] 变成c,b,a |
{e} |
d |
5 |
5=>2(会访问到b,low[d]=min(dfn[b],low[b])=dfn[b]=2), 然后会回溯到c(low[c]=low[d]=dfn[b]=2),最终b的low[b]=dfn[b],b即为根; |
a |
{e}, {d,c,b} |
f |
6 |
6 |
f,a |
{e}, {d,c,b} |
g |
7 |
7=>1会访问到a,low[g]=min(dfn[a],low[g])=dfn[a]=1), 然后会回溯到f(low[f]=low[g]=dfn[a]=1),最终a的low[a]=dfn[a],a即为根; |
空 |
{e}, {d,c,b} {g,f,a} |
本人瞎几把说些吧。。。
在一次DFS的回溯过程中,如果发现low[i]==dfn[i],那么当前顶点就是一个强连通分量的根。
因为如果不是强连通分量的根,那么一定属于另一个强连通分量(好像说了句废话),
而且他的根是当前顶点的祖宗,那么存在包含当前顶点的到其祖宗的回路,
可知最终该顶点v一定会在他的DFS过程中访问到他的祖宗,并且他的Low[v]会被修改成比dfn[v]更小的值,
应该就是其祖宗的dfn[root]值吧。祖宗先访问到,入栈,然后到了下面的子节点,子节点能访问到祖宗,然而他在栈里,
所以一直比较dfn[root],而最小的值只有是dfn[root]和low[root],所以最终root下面顶点low[i]都会等于dfn[root]。OK。
//链式前向星;
struct asd{
int to;
int next;
};
asd edge[N];
int tol,head[N]; int tp; //记录当前访问时间
int p; //栈容量
int dfn[N]; //表示节点i 在DFS过程中的访问序号(也可以叫做开始时间)。
int low[N]; //表示从i 节点出发DFS过程中i 下方节点所能到达的最早的节点的开始时间。
bool vis[N]; //标记是否在栈中 void tarjan(int u)
{
dfn[u]=low[u]=++tp; //初始化
stap[++p]=u; //入栈
vis[u]=1; //标记
for(int v=head[u];v!=-1;v=q[v].next)
{
int i=q[v].to;
if(!dfn[i]) //如果还未被访问
{
tarjan(i);
low[u]=min(low[u],low[i]);
}
else if(vis[i]) //已被访问,且在栈中
low[u]=min(low[u],dfn[i]);
}
if(dfn[u]==low[u]) //如果是根节点
{
int temp;
while(1)
{
temp=stap[p];
vis[temp]=0; //出栈标记;
p--;
if(temp==u) //将该强连通分量弹出栈
break;
}
}
}
萌新学习图的强连通(Tarjan算法)笔记的更多相关文章
- 萌新学习Python爬取B站弹幕+R语言分词demo说明
代码地址如下:http://www.demodashi.com/demo/11578.html 一.写在前面 之前在简书首页看到了Python爬虫的介绍,于是就想着爬取B站弹幕并绘制词云,因此有了这样 ...
- 图之强连通--Tarjan算法
强连通分量 简介 在阅读下列内容之前,请务必了解图论基础部分. 强连通的定义是:有向图 G 强连通是指,G 中任意两个结点连通. 强连通分量(Strongly Connected Components ...
- 【算法•日更•第二十八期】图论:强连通+Tarjan算法(一)
▎前言 一直都想学习这个东西,以为很难,结果发现也不过如此. 只要会些图论的基础就可以了. ▎强连通 ☞『定义』 既然叫强连通,那么一定具有很强的连通性. 强连通:就是指在一个有向图中,两个顶点可以互 ...
- 图的连通性--Tarjan算法
一些概念 无向图: 连通图:在无向图中,任意两点都直接或间接连通,则称该图为连通图.(或者说:任意两点之间都存在可到达的路径) 连通分量: G的 最大连通子图 称为G的连通分量. 有向图 (ps.区别 ...
- HDOJ迷宫城堡(判断强连通 tarjan算法)
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission( ...
- CF:Problem 427C - Checkposts强连通 Tarjan算法
tarjan算法第一题 喷我一脸. ...把手写栈的类型开成了BOOL.一直在找错.. . #include<cstdio> #include<cstring> #includ ...
- 图的连通性——Tarjan算法&割边&割点
tarjan算法 原理: 我们考虑 DFS 搜索树与强连通分量之间的关系. 如果结点 是某个强连通分量在搜索树中遇到的第⼀个结点,那么这个强连通分量的其余结点肯定 是在搜索树中以 为根的⼦树中. 被称 ...
- 萌新学习SpringMVC
前言 只有光头才能变强. 文本已收录至我的GitHub精选文章,欢迎Star:https://github.com/ZhongFuCheng3y/3y 这篇SpringMVC被催了很久了,这阵子由于做 ...
- php萌新|学习|排坑|のmysqli_error()方法的妙用
从开始学习php当现在已经有一个月多.除了每天完成公司布置的日常汇报,也没有耐下性子写一写自己想写的东西.今天就当起个头,坚持一周有个两三片文章或者小总结,也不枉费自己的付出.(我自己都不信,你会信吗 ...
随机推荐
- Android自动折行TextView Group
package com.test.testview; import java.util.ArrayList; import android.content.Context; import androi ...
- 多项式相乘快速算法原理及相应C代码实现---用到fft
最近认真研究了一下算法导论里面的多项式乘法的快速计算问题,主要是用到了FFT,自己也实现了一下,总结如下. 1.多项式乘法 两个多项式相乘即为多项式乘法,例如:3*x^7+4*x^5+1*x^2+5与 ...
- unsigned double
最近犯了一个错误: 定义变量类型的时候竟然定义了unsigned double的类型.由于编译能够通过,因此一直没有发现这样写会有什么样的问题. 今天一次偶然的测试中发现这些变量的值都是整数.一开始觉 ...
- SAM4E单片机之旅——8、UART初步
通信还是比让LED灯闪烁实用得多的. 这次试试使用UART,实现开发版和PC间的通信.功能比较简单,就是把PC发向开发版的内容发送回去.这次主要介绍一下UART的配置,至于通信,则使用较为简单的不断查 ...
- RTSP/RTMP/HLS/HTTP流媒体播放器EasyPlayer
EasyPlayer播放器系列项目 EasyPlayer是由EasyDarwin开源团队开发和维护的一个流媒体播放器系列项目,随着多年不断的发展和迭代,不断基于成功的实践经验,发展出包括有: Easy ...
- jquery 使用ajax,正常返回后,不执行success的问题
背景: 在使用到jQuery的ajax时,如果指定了dataType为json,老是不执行success回调,而是执行了error回调函数. 原因: 然后继续下载了几个jquery版本,如1.3.2, ...
- 分享一个utils.js源码
NEJ.define([ './global.js', '{platform}util.js' ],function(NEJ,_h,_p,_o,_f,_r){ /* * 查看数据是否指定类型 * @p ...
- SE18 BADI定义 / SE19 BADI 实现
明天花30分 再研究下这个: 如果你知道一个BADI名称,可以: 1)使用SE18,输入该BADI名称后,选择Interface,然后查看对应的接口实施样例代码(Example implementat ...
- iOS应用的入口自定义和事件处理的自定义
iOS应用的入口自定义和事件处理的自定义 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: ...
- Android源码的编译和下载【转】
本文转载自:http://blog.csdn.net/banketree/article/details/9089827 网上介绍下载.编译Android方法一坨,读万卷书不如行万里路,以下是笔者亲身 ...