博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
图论初步-Tarjan算法及其应用
阅读量:6002 次
发布时间:2019-06-20

本文共 2099 字,大约阅读时间需要 6 分钟。

暑假刷了一堆Tarjan题到头来还是忘得差不多。

这篇博客权当复习吧。

一些定义

无向图

割顶与桥 (划重点)

图G是连通图,删除一个点表示删除此点以及所有与其相连的边。

若删除某点u后G不再连通,那么u是G的一个割顶(割点)。
若删除某边e后G不再连通,那么e是G的一个

双连通

一个图为双连通,意思是说任一点对(u,v),从u到v都有两条路径。

广义双连通有两种:点双连通(狭义的双连通)、边双连通。

  • 点双连通:就是这两条路径除了起点和终点外无重复点。
  • 边双连通:就是这两条路径无重复边。

例如,两个简单环共一个点的图是边双连通的,但不是点双连通的。

双连通图的性质

点双连通图删除任意一个点仍然连通。

边双连通图删除任意一条边仍然连通。

双连通分量

双连通分量也分为两种。

图G的双连通分量也是G的子图,且保证添加任意其他点、边后都不再是双连通的。
一个顶点可以属于多个点双连通分量,此时这个顶点必定是割顶。
显然,点双连通分量必定是边双连通分量。

哈密顿回路和欧拉回路

哈密顿路是经过所有顶点一次的路径。若起点和终点相同则称哈密顿回路。

欧拉路是经过所有边一次的路径。

有向图

有向图的连通性

  • 强连通:任意点对(u,v),存在从u到v的路径从v到u的路径。
  • 单连通:任意点对(u,v),存在从u到v的路径从v到u的路径。亦称单向连通。
  • 弱联通:忽略边的方向得到的无向图是连通的。此无向图称为该有向图的底图。

单连通图一定是弱连通图。反之则不然。

强连通分量(SCC)(划重点)

亦如上面的定义。有向图G的一个强连通分量是G的一个子图,且任意添加其他点、边都不能再满足强连通的要求。

Tarjan算法

Tarjan求割顶

首先从根节点开始dfs遍历全图,对于每个点我们定义两个数组:\(dfn[],low[]\),其中\(dfn[]\)是这个点的时间戳,用来记录首次访问这个点的时刻;而\(low[]\)则是用来记录从这个点出发所能到达点的最小时间戳。可以配合注释食用。

void tarjan(int u,int fath){    dfn[u]=low[u]=++tmp;        int child=0;    for (int i=head[u];i;i=e[i].nxt){        int v=e[i].to;        if (!dfn[v]){//如果在此之前点v没有被访问过            tarjan(v,u);            low[u]=Min(low[u],low[v]);//更新最小时间戳                        child++;            if (!fath&&child>=2) rec[v]=1;//如果u为根节点且u下有两棵子树那么u一定是割顶            else (fath&&(low[v]>=dfn[u])) rec[v]=1;//如果u有子树的最小时间戳不小于u的时间戳,那么u一定是割顶        }else{            if (u!=fath) low[u]=Min(low[u],dfn[v]);//v的时间戳可能比u小,并且回边不能算        }    }}

Tarjan求桥

和求割顶非常类似

void tarjan(int u,int fath){    dfn[u]=low[u]=++tmp;        int child=0;    for (int i=head[u];i;i=e[i].nxt){        int v=e[i].to;        if (!dfn[v]){            tarjan(v,u);            low[u]=Min(low[u],low[v]);                        child++;            if (dfn[u]

Tarjan求强连通分量

在Tarjan求强连通分量的过程中,low的定义有所改变,并且引入一个栈,low不是能到达的最前的dfn值,而是能到达的仍在栈中的dfn的最前值。

void tarjan(int u){    dfn[u]=low[u]=++timer;    st.push(u); instack[u]=true;    for (int i=0;i

缩点

一般,缩点是针对有向图而言的。

找出了一个有向图的强连通分量后我们可以把每个强连通分量缩为一个点。
如此一来我们便得到一个有向无环图(DAG)。

有了有向无环图,我们就可以在上面跑拓扑。能跑拓朴就能跑dp,因为状态转移的无后效性已经在DAG建立的同时保证了。

例题:

  1. 一句话题解:对于题目中的起点S的处理,在跑Tarjan的时候记录访问过的点,缩点的时候把没访问过的点排除即可。

练习:

Tarjan缩点+DAG+dp模板题:

转载于:https://www.cnblogs.com/hkpls/p/9923628.html

你可能感兴趣的文章
Spring Boot(07)——ConfigurationProperties介绍
查看>>
动力节点Java学习资料为互联网应用文件存储而生之FastDFS
查看>>
go常用辅助工具
查看>>
BeetlSQL 2.11.2 发布,Java Dao 工具
查看>>
为什么我的电脑可以用win10却用不了win7?
查看>>
WPF实现滚动显示的TextBlock
查看>>
Robot Framework之数据类型及变量运算
查看>>
(十二)Java springcloud B2B2C o2o多用户商城 springcloud架构-- SSO单点登录之OAuth2.0 登出流程(3)...
查看>>
WPF MVVM 架构 Step By Step(3)(把后台代码移到一个类中)
查看>>
从PRISM开始学WPF(六)MVVM(二)Command?
查看>>
2018广州云栖大会游戏云专场:阿里云携手虎牙,首次落地直播行业边缘节点及云企业网服务...
查看>>
2017上海QCon之旅总结(下)
查看>>
Chartjs:Line chart的使用及必要参数说明
查看>>
E-MapReduce助力建设企业级数据仓库
查看>>
从服务端视角看高并发难题
查看>>
keras 实现 GAN
查看>>
我必须得告诉你的MySQL优化原理3
查看>>
Android开发 - 掌握ConstraintLayout(九)分组(Group)
查看>>
ASP.NET Core 2 学习笔记(六)MVC
查看>>
基于深度前馈序列记忆网络,如何将语音合成速度提升四倍?
查看>>