搞过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. Nginx反向代理和负载均衡部署指南

    1.        安装 1)         从Nginx官网下载页面(http://nginx.org/en/download.html)下载Nginx最新版本(目前是1.5.13版本)安装包: ...

  2. 通过PHP自带的$_SERVER判断 手机访问网站自动跳转到手机版

    需要有PC版网站和移动版网站,当手机访问域名的时候,通过PHP自带的$_SERVER判断浏览设备并跳转到移动版页面.如果是PC电脑打开网址,则不跳转直接访问pc版. <?php //php判断客 ...

  3. 15、sql语句集,Linux 下PHP查询mysql

    一.mysql 创建数据库 mysql密码,默认没有 如果想更改的话, mysqladmin  -uroot   password  root123 登录   : [root@localhost ro ...

  4. spring的注入

    1 可能遇到的问题: 异常信息 NoSuchBeanDefinitionException: No matching bean of type [...]或是NoSuchBeanDefinitionE ...

  5. 区块链是伟大的,比特币则不然。《FinTech,金融科技时代的来临》。3星。

    本书讲技术给金融业带来的变革和可能的趋势.作者认为区块链是伟大的发明,因为他可以让金融交易免费且实时地进行.比特币则可能会被其他区块链技术取代.书中有至少一半的内容涉及到了区块链和比特币.总体评价3星 ...

  6. Eclipse调试常用技巧

    1. 条件断点 断点大家都比较熟悉,在Eclipse Java 编辑区的行头双击就会得到一个断点,代码会运行到此处时停止. 条件断点,顾名思义就是一个有一定条件的断点,只有满足了用户设置的条件,代码才 ...

  7. [No000088]并行循环vs普通循环

    using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks ...

  8. intellij idea让资源文件自动更新

    intellij idea默认文件是自动保存的,但是手头有个项目jsp文件改动后,在tomcat中不能立即响应变化.要jsp文件改动后立刻看到变化,有个配置.在idea tomcat 中server的 ...

  9. PAT 1034. 有理数四则运算(20)

    本题要求编写程序,计算2个有理数的和.差.积.商. 输入格式: 输入在一行中按照"a1/b1 a2/b2"的格式给出两个分数形式的有理数,其中分子和分母全是整型范围内的整数,负号只 ...

  10. gradle项目中profile的实现

    gradle中并没有直接类似maven中的profile支持,只能变通的用其它方法来处理,在打包不同环境的应用时,通常会遇到二类问题: 一.不同的环境依赖的jar包不同 拿web开发来说,生产环境一般 ...