概念

流图

  给定一个有向图G= (V,E),若存在r∈V满足,满足从r出发能够到达V中所有的点,则称G是一个流图,记为(G,r),其中r是流图的源点。

流图的搜索树

  在一个流图(G,r)上从r出发,进行深度优先遍历(DFS),每个点只访问一次。所有发生递归的变(u,v)(换言之,从x到y是对y的第一次访问)构成的一颗以r为根的树我们把它称为流图(G,r)的搜索树。

时间戳

  同时,我们在深度优先遍历的过程中按照每个节点第一次被访问的时间顺序,依次给予流图中每个点1~n的标记,该点的标记被称作时间戳,用dfn[u]表示。

追溯值

  设subtree(u)是以u为根的子树。u的追溯值low[u]我们这样定义满足以下条件中任意一个的点v的最小时间戳:

  • 从u出发的边指向的点v在栈中。
  • 在搜索树上以u为根的子树上的点v。

边的分类

对于流图中的有向边(u,v),必是以下四种边之一:

  • 树枝边,指的是搜索树中的边,即u是y的父亲节点。
  • 前向边,指的是搜索树中u是v的祖先节点。
  • 后向边,指的是搜索树中v是u的祖先节点。
  • 横叉边,指的是除了以上三种边之外的边,它一定满足dfn[v] <dfn[u]。

算法流程

  1. 当前节点u第一次被访问时,把u入栈,初始化low[u] = dfn[u].
  2. 扫描从u出发的每一条边(u,v)。
    • 若v没被访问过,则说明(u,v)是树枝边,递归访问v,从y回溯之后,令low[u] = min(low[u], low[v])。
    • 若v别访问过并且v在栈中,则令low[u] = min(low[x], dfn[v]);
  3. 从v回溯之前,判断是否有(low[u] == dfn[u])。若成立,则不断从栈中弹出节点,直至u出栈。

p.s.绿色的点是当前访问的点,黄色的点是已经访问结束的点,灰色的点是未访问完全(正在访问以它为根节点的子树);

p.s.p.s.黑色的序号代表节点的编号,蓝色的序号代表该点的dfn值,红色的序号代表该点的low值;

p.s.p.s.p.s.红色的边代表树枝边,深蓝色的边代表前向边,水蓝色的边代表后向边,橙色的边代表横叉边。

代码

#include<bits/stdc++.h>
using namespace std; const int MAXN = , MAXM = ; //加边
int Head[MAXN], Next[MAXM], To[MAXM], edgenum = ;
inline void Add_edge(int from, int to)
{
Next[++ edgenum] = Head[from], Head[from] = edgenum, To[edgenum] = to;
} //tarjan
int dfn[MAXN], ti = , sta[MAXN], top = , color[MAXN], cnt = , low[MAXN], num[MAXN], vis[MAXN];
inline void dfs(int u)
{
dfn[u] = low[u] = ++ ti, vis[u] = , sta[++ top] = u;
for(int i = Head[u]; i != -; i = Next[i])
{
int v = To[i];
if(!dfn[v])
{
dfs(v);
low[u] = min(low[u], low[v]);
}
else
if(vis[v]) low[u] = min(dfn[v], low[u]);
}
if(dfn[u] == low[u])
{
color[u] = ++cnt;
num[cnt] ++;
for(;sta[top] != u;)
{
color[sta[top]] = cnt;
vis[sta[top]] = ;
num[cnt] ++;
top --;
}
top --;
}
return;
}
inline int tarjan(int n)
{
int ans = ;
for(int u = ; u <= n; ++ u)
if(!color[u]) dfs(u);
for(int i = ; i <= cnt; ++ i)
if(num[i] > ) ans ++;
return ans;
} int main()
{
memset(Head, -, sizeof(Head));
int n, m;
scanf("%d%d", &n, &m);
for(int i = ; i <= m; ++ i)
{
int x, y;
scanf("%d%d", &x, &y);
Add_edge(x, y);
}
printf("%d\n", tarjan(n));
return ;
}

【模板】Tarjan算法与有向图的强连通性的更多相关文章

  1. Kosaraju 算法检测有向图的强连通性

    给定一个有向图 G = (V, E) ,对于任意一对顶点 u 和 v,有 u --> v 和 v --> u,亦即,顶点 u 和 v 是互相可达的,则说明该图 G 是强连通的(Strong ...

  2. [Tarjan系列] Tarjan算法与有向图的SCC

    前面的文章介绍了如何用Tarjan算法计算无向图中的e-DCC和v-DCC以及如何缩点. 本篇文章资料参考:李煜东<算法竞赛进阶指南> 这一篇我们讲如何用Tarjan算法求有向图的SCC( ...

  3. Tarjan算法求有向图强连通分量并缩点

    // Tarjan算法求有向图强连通分量并缩点 #include<iostream> #include<cstdio> #include<cstring> #inc ...

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

    百度百科 https://baike.baidu.com/item/tarjan%E7%AE%97%E6%B3%95/10687825?fr=aladdin 参考博文 http://blog.csdn ...

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

    算法描述 tarjan算法思想:从一个点开始,进行深度优先遍历,同时记录到达该点的时间(dfn记录到达i点的时间),和该点能直接或间接到达的点中的最早的时间(low[i]记录这个值,其中low的初始值 ...

  6. tarjan算法-解决有向图中求强连通分量的利器

    小引 看到这个名词-tarjan,大家首先想到的肯定是又是一个以外国人名字命名的算法.说实话真的是很佩服那些算法大牛们,佩服得简直是五体投地啊.今天就遇到一道与求解有向图中强连通分量的问题,我的思路就 ...

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

    有向图的强连通分量 定义:在有向图\(G\)中,如果两个顶点\(v_i,v_j\)间\((v_i>v_j)\)有一条从\(v_i\)到\(v_j\)的有向路径,同时还有一条从\(v_j\)到\( ...

  8. 强连通分量的Tarjan算法

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

  9. HDU 1269 迷宫城堡 tarjan算法求强连通分量

    基础模板题,应用tarjan算法求有向图的强连通分量,tarjan在此处的实现方法为:使用栈储存已经访问过的点,当访问的点离开dfs的时候,判断这个点的low值是否等于它的出生日期dfn值,如果相等, ...

随机推荐

  1. MySQL---6、可视化工具工具之SQLYog安装配置

    一.安装文件包下载 https://pan.baidu.com/share/link?shareid=4149265923&uk=724365661&fid=2642450782 二. ...

  2. jQuery选择器,外加例子讲解

    jQuery选择器的优势: (1) 代码更简单(2) 支持CSS1到CSS3选择器(3) 完善的处理机制 jQuery选择器的分类 (1) 基本选择器 基本选择器是jQuery中使用最多的选择器,它又 ...

  3. Java - 复合模式优于继承

    继承是实现代码重用的方法之一,但使用不当则会导致诸多问题. 继承会破坏封装性,对一个具体类进行跨包访问级别的继承很危险. 即,子类依赖父类的实现细节. 如果父类的实现细节发生变化,子类则可能遭到破坏. ...

  4. JS获取当前屏幕宽高

    Javascript: 网页可见区域宽: document.body.clientWidth网页可见区域高: document.body.clientHeight网页可见区域宽: document.b ...

  5. [javaEE] Servlet中Session的使用

    Session是一个域 作用范围:当前会话范围 生命周期:当程序第一次调用request.getSession()创建出客户端的session对象,30分钟没有操作认为超时,这个可以在web.xml中 ...

  6. 阿里云CentOS7 64位安装jdk8和mysql5.6.43及远程连接mysql

    安装mysql 先查看系统是否安装有mysql rpm -qa | grep mysql 返回空值说明没有,有的话先删除 yum remove mysql 下载mysql的repo源 wget htt ...

  7. layui登录后token问题

    layui是一个非常简单且实用的后台管理系统搭建框架,里面的插件丰富使用简单,只需要在原有基础上进行修改即可,但是在数据处理方面略显薄弱,内置的jquery在实际过程中略显不足,若是能添加内置的mvc ...

  8. springboot的依赖注入报null的问题

    最近使用springboot开发项目,使用到了依赖注入,频繁的碰到注入的对象报空指针,错误如下 java.lang.NullPointerException: null at com.mayihc.a ...

  9. log4j2配置文件

    项目里面经常用到日志,Java开发一般用log4j.slf4j这些框架,看着配置文件有点懵.这几天看公司代码的时候,也有用到log4j,感觉要复杂一点.在本地打log,也有打到hive里面存的.看了一 ...

  10. DBUtils结果集处理器介绍

    common-dbutils.jar是Apache组织提供的一个对JDBC进行简单封装的开源工具类库,使用它能够简化JDBC应用程序的开发,同时也不会影响程序的性能. 1.QueryRunner类 ① ...