搞过OI的对tarjan这个人大概都不陌生。这个人发明了很多神奇的算法,在OI届广被采用。

他最广泛采用的三个算法都是和$dfn$,$low$相关的。

有向图求强连通分量

其实说直白点,就是缩点。用得比较多的就是把一个有向有环图变为一个DAG。然后利用DAG的一些神奇的性质求解一些常见的问题。

核心代码如下:

void tarjan(int node){
    vis[node]=1;dfn[node]=low[node]=++dfs_clock;
    stack[++top]=node;
    for(int i=LINK[node];i;i=e[i].next)
        if(!dfn[e[i].y]){
            tarjan(e[i].y);
            low[node]=min(low[node],low[e[i].y]);
        }else if(vis[e[i].y])    low[node]=min(low[node],dfn[e[i].y]);
	if(dfn[node]==low[node]){
		group_num++;
		int tmp;
		do{
			tmp=stack[top--];
			vis[tmp]=0;
			group[tmp]=group_num;
		}while(tmp!=node);
	}
}

每次执行完后,$group$值相同的就是强连通分量里的。同时$group_{num}$也代表这里有几个强连通分量。

需要注意的是,这个只适用于有向图的缩点建图。如果以这个为模板特判父亲然后妄想把无向图缩成一棵树就是大错特错,至于有向图的缩点请参考下面的点双联通分量

无向图求割点/割边

求割点和割边其实无差,如果一个点存在一条边为割边,那么这个点一定是割点.

相应的,对于点$node$的儿子$son$,如果$dfn[node] \leq low[son] $,那么$edge_{(node,son)}$就是一条割边,而$node$也就是相应的割点。

特殊的,如果$node$为$root$,且只有一个儿子,也满足上述条件,但显然$node$不是割点,所有需要特判。

void tarjan(int node,int father){
    vis[node]=1;dfn[node]=low[node]=++dfs_clock;
    for(int i=LINK[node];i;i=e[i].next)if(e[i].y!=father){
        if(!dfn[e[i].y]){
            outdu[node]++;
            tarjan(e[i].y,node);
            cmin(low[node],low[e[i].y]);
            if(low[e[i].y]>=dfn[node])OK[node]=1;
        }else if(vis[e[i].y]) cmin(low[node],dfn[e[i].y]);
    }
    if(outdu[node]==1&&node==1)OK[node]=0;
}

无向图求点双联通分量

这一块相对来说比较复杂,可以去做一道题。什么是点双联通分量?直白点说就是从一个点到另一个点的一个"圈"。

之前说到了用求强连通分量的方法不能把一个图缩成树来搞,可以参考一下这张图。

如果只用那种方法,这整张图都会被缩成一个点,但是显然这个图应该是两个点双联通分量。

可以注意到,连接着两个点双联通分量的点是一个割点,因此可以借用之前思路来求解求解点双联通分量。

void tarjan(int node){
    dfn[node]=low[node]=++dfs_clock;
    stack[++top]=node;int son=0;
    Auto(i,node)if(!dfn[e[i].y]){
        tarjan(e[i].y);
        cmin(low[node],low[e[i].y]);
        if(low[e[i].y]>=dfn[node]){
            int tmp;group_num++;
            do{
                tmp=stack[top--];
                group[group_num].pb(tmp);
            }while(tmp!=e[i].y);
            group[group_num].pb(node);
        }
    }else cmin(low[node],dfn[e[i].y]);
}

乍一看好像和求强连通分量没什么区别,确实。这个只是把我们称之为缩点的过程移到了循环里。

在建树的时候也跟第一个的构建新图不是很一样。对于每个点双联通分量,新建一个点,这个点向点双联通分量里的每个点连边。最终一定能构成一棵树,而这个树上任意两点之间的路径上所包含的点(除虚点)都是在原图上必经的点。

Tarjan三把刀的更多相关文章

  1. 我的runloop学习笔记

    前言:公司项目终于忙的差不多了,最近比较闲,想起叶大说过的iOS面试三把刀,GCD.runtime.runloop,runtime之前已经总结过了,GCD在另一篇博客里也做了一些小总结,今天准备把ru ...

  2. Solr学习(2) Solr4.2.0+IK Analyzer 2012

    Solr学习(二) Solr4.2.0+IK Analyzer 2012 开场白: 本章简单讲述如何在solr中配置著名的 IK Analyzer 分词器. 本章建立在 Solr学习(一)  基础上进 ...

  3. 自学JQuery Mobile的几个例子

    JQuery Mobile是一个用于构建移动Web应用程序的框架,适用于主流的移动设备(智能手机.平板电脑),该框架利用了HTML5和CSS3技术减少了额外的脚本文件的编写.具体JQuery Mobi ...

  4. android开发 RecyclerView 列表布局

    创建一个一行的自定义布局 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns ...

  5. hihoCoder 1185 连通性·三(Tarjan缩点+暴力DFS)

    #1185 : 连通性·三 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 暑假到了!!小Hi和小Ho为了体验生活,来到了住在大草原的约翰家.今天一大早,约翰因为有事要出 ...

  6. 《程序员代码面试指南》第三章 二叉树问题 Tarjan算法与并查集解决二叉树节点间最近公共祖先的批量查询问题

    题目待续.... Tarjan算法与并查集解决二叉树节点间最近公共祖先的批量查询问题 java代码

  7. Tarjan在图论中的应用(三)——用Tarjan来求解2-SAT

    前言 \(2-SAT\)的解法不止一种(例如暴搜?),但最高效的应该还是\(Tarjan\). 说来其实我早就写过用\(Tarjan\)求解\(2-SAT\)的题目了(就是这道题:[2019.8.14 ...

  8. Newnode's NOI(P?)模拟赛 第三题 (主席树优化建图 + tarjan)

    题目/题解戳这里 这道题题目保证a,b,ca,b,ca,b,c各是一个排列-mdzz考场上想到正解但是没看到是排列,相等的情况想了半天-然后写了暴力60分走人- 由于两两间关系一定,那么就是一个竞赛图 ...

  9. OO第三单元——基于JML的社交网络总结

    OO第三单元--基于JML的社交网络总结 一.JML知识梳理 1)JML的语言基础以及基本语法 JML是用于java程序进行规格化设计的一种表示语言,是一种行为接口规格语言.其为严格的程序设计提供了一 ...

随机推荐

  1. SQL Like模糊查询一些小知识

    模糊查询: where mc like '值':返回值等同于where mc ='值' where mc like '%值':匹配 名称是 '*值'(以“值”作为结尾)的所有数据,*表示任何值任何长度 ...

  2. 【Linux学习】Vi 操作命令集合

    Vi 操作命令集合 进入vi的命令 vi filename :打开或新建文件,并将光标置于第一行首 vi +n filename :打开文件,并将光标置于第n行首 vi + filename :打开文 ...

  3. Centos 6.5 安装ELK

    安装java 查看java安装路径 修改环境变量 添加如下内容: export JAVA_HOME=/usr/java/jdk1.8.0_91 export PATH=$JAVA_HOME/bin:$ ...

  4. mysql 主从复制配置

    环境:已经在centos下安装好mysql,安装参考:http://www.cnblogs.com/bookwed/p/5896619.html,安装好主数据库后,可以克隆一份,注意修改ip等. 19 ...

  5. [WPF系列]-DataBinding 绑定计算表达式

            Width="{Binding RelativeSource={RelativeSource Self}, Path=ActualWidth, Converter={Stat ...

  6. BI商务智能对于企业的意义

    BI商务智能之所以越来越重要,是因为无知是现代企业的最大威胁.不知不觉的风险是巨大的,而一知半解可能比一无所知危害更大,因为我们会带着错误的念头做出决定和采取行动,同时还自鸣得意地认为自己是真理的化身 ...

  7. 帆软报表FineReport数据库连接编码转换

    1. 问题描述 数据库会以某种编码方式保存与读取数据,FineReport解析时默认使用GBK字符集,若数据库端编码与设计器端编码不一致时,就会导致中文及特殊字符的乱码. FineReport在定义数 ...

  8. 帆软报表FineReport中数据连接之Tomcat配置JNDI连接

    1. 问题描述 在帆软报表FineReport中,通过JNDI方式定义数据连接,首先在Tomcat服务器配置好JNDI,然后在设计器中直接调用JNDI的名字,即可成功使用JNDI连接,连接步骤如下: ...

  9. sass入门

    SASS是一种CSS的开发工具,提供了许多便利的写法,大大节省了设计者的时间,使得CSS的开发,变得简单和可维护. SASS 官网介绍: sass is the most mature(成熟的),st ...

  10. win7如何恢复以前的ie版本

    如何恢复以前的ie版本-控制面板,程序和功能-查看已安装的更新-搜索Internet explorer,然后卸载更新就Ok.