搞过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. CLR线程概览(下)

    作者:施懿民链接:https://zhuanlan.zhihu.com/p/20866017来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 同步: 托管代码 托管代码可 ...

  2. 【转】Java并发编程:volatile关键字解析

    转自:http://www.importnew.com/18126.html#comment-487304 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备 ...

  3. ARM汇编与C混合编程

    GNU内联汇编 内联汇编即在C中直接使用汇编语句进行编程,使程序可以在C程序中实现C语言不能完成的一些工作,例如,在下面几种情况中必须使用内联汇编或嵌入型汇编 程序中使用饱和算术运算(Saturati ...

  4. 一致性哈希算法与Java实现

    原文:http://blog.csdn.net/wuhuan_wp/article/details/7010071 一致性哈希算法是分布式系统中常用的算法.比如,一个分布式的存储系统,要将数据存储到具 ...

  5. Windows7开机登录界面背景图修改

    首先,准备一张文件大小不超过250K的.jpg格式图片,文件名为:BackgroundDefault,图片分辨率建议与屏幕分辨率一致,因为这张背景无法像壁纸一样拉伸或者填充的. 打开这个路径,[C:\ ...

  6. 【转载】4412开发板嵌入式QtE应用开发环境搭建

    本文转自迅为iTOP-4412开发板实战教程书籍:http://topeetboard.com QtE应用需要使用开发工具qtcreator,本文介绍qtcreator-3.2.2的安装和使用.1. ...

  7. Media Queries 详解

    Media Queries直译过来就是“媒体查询”,在我们平时的Web页面中head部分常看到这样的一段代码:  <link href="css/reset.css" rel ...

  8. Libevent的IO复用技术和定时事件原理

    Libevent 是一个用C语言编写的.轻量级的开源高性能网络库,主要有以下几个亮点:事件驱动( event-driven),高性能;轻量级,专注于网络,不如 ACE 那么臃肿庞大:源代码相当精炼.易 ...

  9. postman使用之三:API请求和查看响应结果

    请求 postman支持很多请求类型,界面左侧可以看到请求类型:get.post.put.patch等,右侧是发送和保存按钮,下方是请求支持的认证方式.信息头.信息体.私有脚本和测试结果.下面我们介绍 ...

  10. 1089 最长回文子串 V2(Manacher算法)

    1089 最长回文子串 V2(Manacher算法) 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 回文串是指aba.abba.cccbccc.aaaa ...