图论初步-Tarjan算法及其应用
暑假刷了一堆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]<low[v]){e[++cnt].u=u;e[cnt].v=v;}
}else {if (u!=fath) low[u]=Min(low[u],dfn[v]);}
}
}
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<e[u].size();i++) {
int v=e[u][i];
if (dfn[v]==0) {//如果访问过v
tarjan(v);
low[u]=min(low[u],low[v]);//更新最小时间戳
} else if (instack[v]) {//如果在栈内(在同一个强连通分量内)
low[u]=min(low[u],dfn[v]);
/*同low[u]=min(low[u],low[v]);
LXQ:求scc应该都可以-.-因为你一旦找到了上一个scc那它们就都出栈了-.-所以后面更新判断是否在栈中就保证了更新的值都是可行的
求scc不存在割顶的问题所以应该都可以
Upd.其实就是说已经走过的v在栈内,但是由于递归没有回溯,所以此时dfn[v]==low[v]*/
}
}
if (dfn[u]==low[u]) {//这就是一个强连通分量的根节点
int m;
printf("SCC: ");
do {
m=st.top();
st.pop();/*使栈顶出栈,把该强连通分量内除根节点外的
所有点弹出*/
instack[m]=false;
printf("%d ",m);
} while (m!=u);
printf("\n");
}
}
缩点
一般,缩点是针对有向图而言的。
找出了一个有向图的强连通分量后我们可以把每个强连通分量缩为一个点。
如此一来我们便得到一个有向无环图(DAG)。
有了有向无环图,我们就可以在上面跑拓扑。能跑拓朴就能跑dp,因为状态转移的无后效性已经在DAG建立的同时保证了。
例题:
- Luogu_3627_[APIO2009]抢掠计划
一句话题解:对于题目中的起点S的处理,在跑Tarjan的时候记录访问过的点,缩点的时候把没访问过的点排除即可。
练习:
Tarjan缩点+DAG+dp模板题:
Luogu_3387_【模板】缩点
Luogu_4742_[Wind Festival]Running In The Sky
图论初步-Tarjan算法及其应用的更多相关文章
- 图论1 Tarjan算法
强连通分量 模板(强联通分量个数+缩点) #include<iostream> #include<cstdio> #define MAXn 100000 #define MAX ...
- 图论:Tarjan算法
在有向图中,若两点至少包含一条路径可以到达,则称两个顶点强连通,若任意两个顶点皆如此,则称此图为强联通图.非强连通图有向图的极大强连通子图,称为强连通分量(strongly connected com ...
- 『图论』有向图强连通分量的Tarjan算法
在图论中,一个有向图被成为是强连通的(strongly connected)当且仅当每一对不相同结点u和v间既存在从u到v的路径也存在从v到u的路径.有向图的极大强连通子图(这里指点数极大)被称为强连 ...
- 【原创】tarjan算法初步(强连通子图缩点)
[原创]tarjan算法初步(强连通子图缩点) tarjan算法的思路不是一般的绕!!(不过既然是求强连通子图这样的回路也就可以稍微原谅了..) 但是研究tarjan之前总得知道强连通分量是什么吧.. ...
- 【算法•日更•第二十八期】图论:强连通+Tarjan算法(一)
▎前言 一直都想学习这个东西,以为很难,结果发现也不过如此. 只要会些图论的基础就可以了. ▎强连通 ☞『定义』 既然叫强连通,那么一定具有很强的连通性. 强连通:就是指在一个有向图中,两个顶点可以互 ...
- ACM(图论)——tarjan算法详解
---恢复内容开始--- tarjan算法介绍: 一种由Robert Tarjan提出的求解有向图强连通分量的线性时间的算法.通过变形,其亦可以求解无向图问题 桥: 割点: 连通分量: 适用问题: 求 ...
- 图论分支-Tarjan初步-割点和割边
所谓割点(顶)割边,我们引进一个概念 割点:删掉它之后(删掉所有跟它相连的边),图必然会分裂成两个或两个以上的子图. 割边(桥):删掉一条边后,图必然会分裂成两个或两个以上的子图,又称桥. 这样大家就 ...
- 图论-强连通分量-Tarjan算法
有关概念: 如果图中两个结点可以相互通达,则称两个结点强连通. 如果有向图G的每两个结点都强连通,称G是一个强连通图. 有向图的极大强连通子图(没有被其他强连通子图包含),称为强连通分量.(这个定义在 ...
- Light OJ - 1026 - Critical Links(图论-Tarjan算法求无向图的桥数) - 带详细注释
原题链接 无向连通图中,如果删除某边后,图变成不连通,则称该边为桥. 也可以先用Tajan()进行dfs算出所有点 的low和dfn值,并记录dfs过程中每个 点的父节点:然后再把所有点遍历一遍 ...
随机推荐
- python使用进程池多进程时,如何打印错误信息
一.说明 1.python进程池进行多进程运行时,如果有错误,该进程会直接跳过,并且不会打印错误信息. 2.如果需要了解到进程内的错误信息,此时就需要通过捕获异常来输出错误信息了. 二.具体方法如下: ...
- Django搭建后篇——启动服务器及创建视图
开启服务器,Django开启服务器的方式有两种,一种是在Ubuntu在开启,另一种是直接在pycharm开启.就方便而言肯定是第二种,但由于pycharm版本的问题,可能有的人无法直接在pycharm ...
- StringBuiler和StringBuffer的区别
String.StringBuiler.和StringBuffer都是可以对字符串进行处理的类,他们3个的主要区别在于,运行的速度,还有运行时的线程安全问题. 运行速度方面,它们的快慢顺序依次为:St ...
- windows下隐藏文件夹
在cmd中找到文件夹所在的路径,然后执行以下命令 隐藏文件:attrib 文件名 +s +h 显示隐藏文件:attrib 文件名 -s -h 后记:attrib指令用于修改文件的属性,文件的常见属性有 ...
- 吴裕雄--天生自然 pythonTensorFlow图形数据处理:将MNIST手写图片数据写入TFRecord文件
import numpy as np import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_dat ...
- Tomcat远程debug配置
当我们需要定位生产环境问题,而日志又不清晰的情况下,我们可以借助Tomcat提供的远程调试,设置如下: // Linxu系统: apach/bin/startup.sh开始处中增加如下内容: decl ...
- logstash 使用glusterfs网络存储偶发性文件解析异常的问题
其实问题到现在为止也没有解决 因为服务是部署在k8s上,挂载的,偶发性的出现文件解析异常 bom头已经验证过了 手动重新解析这些文件完全正常,问题无法复现,文件本身并没有问题. 最后怀疑到了最不该怀疑 ...
- SQL Server Driver for PHP之sqlsrv相关函数
SQL Server Driver for PHP 包含以下函数: 函数 说明 sqlsrv_begin_transaction 开始事务. sqlsrv_cancel 取消语句:并放弃相应语句的所有 ...
- [一般图最大匹配]Bimatching
10566 Bimatching 题意:一个男生必须跟两个女生匹配,求最大匹配 思路:一般的二分图匹配做不了,网络流也不会建图,这题采用的是一般图匹配 首先在原来二分图的基础上,将一个男生拆成两个点 ...
- python3.7解释器安装及配置虚拟环境
目录 环境准备 一.开始安装解释器(安装很简单,直接上图) 二.配置pip工具下载源 安装虚拟环境 环境准备 1.Windows系统,本人是 Windows10专业版 2.python解释器安装包,本 ...