Tarjan是谁

Tarjan's SCCs(有向图强连通分量)algorithm

给定⼀个有向图 \(G\),若存在 \(rt\in V\),满⾜从 \(rt\) 出发能到达 \(V\) 中的所有的点,则称 \(G\) 是⼀个源点为 \(rt\) 流图。

从 \(rt\) 出发做 \(DFS\)。

符号表

  • \(fa[x]\):\(x\) 节点的父亲节点

  • \(anc[x]\):\(x\) 节点的祖先点集

  • \(son[x]\):搜索树中 \(x\) 节点的儿子节点集

  • \(e[x]\):\(\{y \ | \ (x \to y)\in E\}\)

  • \(dfn[x]\):\(x\) 节点的时间戳

  • \(sbt[x]\):\(x\) 节点为根的子树点集

  • \(low[x]\):\(x\) 节点的追溯值

\(G\) 中的每条有向边 \(x\to y\) 必然是以下四种之⼀:

  • 枝:\(x=fa[y]\)

  • 前:\(x\in (anc[y]-fa[y])\)

  • 后:\(y\in (anc[x]-fa[x])\)

  • 横:\(x\notin anc[y] \ \and \ y\notin anc[x]\) 此时一定满足 \(dfn[x]>dfn[y]\)

节点上的数字为时间戳:

分析

我们在搜索树上分析,发现“前”边没有什么用处,因为搜索树上本来就存在从 \(x\) 到 \(y\) 的路径。“后”边非常有用,它可以和搜索树上从 \(x\) 到 \(y\) 的路径⼀起构成环。“横”边要看情况,如果从 \(y\) 出发能找到⼀条路径回到 \(x\) 的祖先节点,那么 \(x\to y\) 就是有用的。

\(low[x]\) 定义为满⾜以下条件的节点的最小时间戳:

  • 该点在栈中。

  • 存在⼀条从 \(sbt[x]\) 出发的有向边,以该点为终点。

\(tarjan(x)\) 主体

  1. \(low[x]=dfn[x]=++dfn\_time\)

  2. \(for(y:e[x])\begin{cases}tarjan(y) \ check\_min(low[x],\color{blue}{low[y]}) & !vis[y] \\ check\_min(low[x],\color{red}{dfn[y]}) & y\in anc[x] \\ do \ nothing & otherwise\end{cases}\)

  3. \(if(low[x]=dfn[x]) \ pop \ stack \ until \ x \ is \ popped \to a \ SCC\)

注意标红和标蓝的不能改,不能错!!!

Code

P1407 [国家集训队]稳定婚姻

vector<int> e[N];
int dfn[N];//时间戳
int low[N];//追溯值
int tim=0;//时间戳计数器
int col[N];//所属 SCC (为其中一个点的 id)
int st[N];//stack
int tot=0;//stack_top
bool in[N];//是(1)否(0)在栈中
void tar(int x){
dfn[x]=low[x]=++tim;//init
st[++tot]=x;//进栈
in[x]=1;
for(int i:e[x]){
if(!dfn[i]){//萌新
tar(i);//递归
ckmn(low[x],low[i]);
}else if(in[i]){//祖先
ckmn(low[x],dfn[i]);
}
}
if(low[x]==dfn[x]){//导出 SCC
do{
col[st[tot]]=x;
//着上 x 的颜色,以后你就是 x 的人了
in[st[tot]]=0;
}while(st[tot--]!=x);//pop until x popped
}
}

Tarjan's BCCs(无向图双连通分量)algorithm

与 SCC 类似,所以符号沿用

注意此时 \(low[x]\) 的定义改变,且图 \(G\) 中不再存在意义上的“横”边、“前”边。

\(low[x]\) 定义为满⾜以下条件之一的节点的最小时间戳:

  • 该点在 \(sbt[x]\) 中。

  • 存在⼀条从该点出发至 \(sbt[x]\) 中任一点的非树边。

剩下的分析和算法就一样了~

桥

桥⼀定是搜索树上的边。

\[x\leftrightarrow fa[x] 为桥 \iff dfn[fa[x]]<low[x]
\]

Code by FuZhenTao

const int SIZE=100010;
int head[SIZE],ver[SIZE*2],nxt[SIZE*2];
int dfn[SIZE],low[SIZE],n,m,tot,num;
bool bridge[SIZE*2];
void add(int x,int y){
ver[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
void tarjan(int x,int in_edge){
dfn[x]=low[x]=++num;
for(int i=head[x];i;i=nxt[i]){
int y=ver[i];
if(!dfn[y]){
tarjan(y,i);
low[x]=min(low[x],low[y]);
if(low[y]>dfn[x]) bridge[i]=bridge[i^1]=true;
}
else if(i!=(in_edge^1)){
low[x]=min(low[x],dfn[y]);
}
}
}
int main(){
cin>>n>>m;
tot=1;
for(int i=1;i<=m;i++){
int x,y;
cin>>x>>y;
add(x,y);
add(y,x);
}
for(int i=1;i<=n;i++){
if(!dfn[i]) tarjan(i,0);
}
for(int i=2;i<tot;i+=2){
if(bridge[i]) cout<<ver[i^1]<<" "<<ver[i]<<endl;
}
}

割点

\[x 为割点 \iff \begin{cases}| \ son[x] \ |>1 & x=rt\\ \exists y\in son[x] \ , \ dfn[x]\leqslant low[y] & x\ne rt\end{cases}
\]

Code by FuZhenTao

void tarjan(int x){
dfn[x]=low[x]=++num;
int flag=0;
for(int i=head[x];i;i=nxt[i]){
int y=ver[i];
if(!dfn[y]){
tarjan(y);
low[x]=min(low[x],low[y]);
if(low[y]>=dfn[x]){
flag++;
if(x!=root||flag>1) cut[x]=true;
}
}
else low[x]=min(low[x],dfn[y]);
}
}

e-DCC(边双连通分量)

设 \(G\) 是无向连通图。

\[G 是 e-DCC \iff \kappa'(G)\geqslant2 \iff 任意⼀条边都包含在至少⼀个简单环中
\]

只需要求出无向图中所有的桥,把桥都删除之后,图会分成若干个连通块,每个连通块就是⼀个"边双连通分量"。

Code by FuZhenTao

int c[SIZE],dcc;
void dfs(int x){
c[x]=dcc;
for(int i=head[x];i;i=nxt[i]){
int y=ver[i];
if(c[y]||bridge[i]) continue;
dfs(y);
}
}
for(int i=1;i<=n;i++){
if(!c[i]){
++dcc;
dfs(i);
}
}

v-DCC(点双连通分量)

\[G 是 v-DCC \iff \kappa(G)\geqslant2 \iff n(G)\leqslant2 \or 任意两点都包含在至少⼀个简单环中
\]

v-DCC 的求法炒鸡麻烦,鸽了。

由于 Tarjan \(O(n)\) 求 LCA 好像并不是 Tarjan 的算法,而且倍增 \(O(n\log n)\) 好用并好写,所以就不再论述了。

重修 Tarjan的更多相关文章

  1. HDU4738 tarjan割边|割边、割点模板

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=4738 坑点: 处理重边 图可能不连通,要输出0 若求出的结果是0,则要输出1,因为最少要派一个人 #inc ...

  2. bzoj 1179[Apio2009]Atm (tarjan+spfa)

    题目 输入 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每行一 ...

  3. tarjan讲解(用codevs1332(tarjan的裸题)讲解)

    主要借助这道比较裸的题来讲一下tarjan这种算法 tarjan是一种求解有向图强连通分量的线性时间的算法.(用dfs来实现) 如果两个顶点可以相互通达,则称两个顶点强连通.如果有向图G的每两个顶点都 ...

  4. NOIP2009最优贸易[spfa变形|tarjan 缩点 DP]

    题目描述 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个 城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分 为双向通行的道路 ...

  5. Tarjan

    //求强连通分量 void uni(int x,int y){ if (rank[x]<rank[y]){ fa[x]=y; size[y]+=size[x]; }else{ rank[x]+= ...

  6. 【UOJ#67】新年的毒瘤 Tarjan 割点

    #67. 新年的毒瘤 UOJ直接黏贴会炸...    还是戳这里吧: http://uoj.ac/problem/67#tab-statement Solution 看到这题的标签就进来看了一眼. 想 ...

  7. 【Codefoces487E/UOJ#30】Tourists Tarjan 点双连通分量 + 树链剖分

    E. Tourists time limit per test: 2 seconds memory limit per test: 256 megabytes input: standard inpu ...

  8. 【BZOJ-1123】BLO Tarjan 点双连通分量

    1123: [POI2008]BLO Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 970  Solved: 408[Submit][Status][ ...

  9. 【BZOJ-2730】矿场搭建 Tarjan 双连通分量

    2730: [HNOI2012]矿场搭建 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1602  Solved: 751[Submit][Statu ...

随机推荐

  1. 腾讯云 TKE Everywhere 特性发布,用户可在自有基础设施中托管 K8s 服务

    作者 孔令飞,腾讯云资深工程师,拥有大规模 Kubernetes 集群.微服务的研发和架构经验,目前专注于云原生混合云领域的基础架构开发. 朱翔,腾讯云容器服务高级产品经理,目前负责云原生混合云产品方 ...

  2. 接上一篇安装linux问题,解决redis安装后make test错误

    (file "tests/helpers/bg_complex_data.tcl" line 10) Killing still running Redis server 3987 ...

  3. Ubuntu 16.04 + Win10双系统 启动Ubuntu进入命令行 无界面

    Ubuntu 16.04 + Win10双系统,启动Ubuntu时候报错,并入命令行(无界面). 原因:可能是双系统兼容性问题 解决办法: 重启系统,进入Win10 然后在Win10中重启电脑. 重启 ...

  4. 一、docker部署Jenkins

    1.部署启动脚本: [root@node10 docker-data]# cat start.sh docker run -d \ --restart=unless-stopped \ -v /opt ...

  5. ELK 收集 Tomcat日志以及修改Tomcat日志格式

    ELK 收集 Tomcat日志以及修改Tomcat日志格式 Tomcat日志 想要收集tomcat 日志 首先我们要对tomcat的日志有足够的了解 tomca日志分类 简单的说tomcat logs ...

  6. Dockerfile简介及基于centos7的jdk镜像制作

    Dockerfile简介 dockerfile 是一个文本格式的配置文件, 用户可以使用 Dockerfile 来快速创建自定义的镜像, 另外,使用Dockerfile去构建镜像好比使用pom去构建m ...

  7. java多线程 synchronized 与lock锁 实现线程安全

    如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的. 通过卖火车票的例子 火车站要卖票,我们模 ...

  8. 《微服务架构设计模式》读书笔记 | 第8章 外部API模式

    目录 前言 1. 外部API的设计难题 1.1 FTGO应用程序的服务及客户端 1.2 FTGO移动客户端API的设计难题 1.3 其他类型客户端API的设计难题与特点 2. API Gateway模 ...

  9. AI:用软件逻辑做硬件爆款

    "我们的野心不止那么一点点." 百度集团副总裁.百度智能生活事业群组(SLG)总经理.小度CEO景鲲曾多次对外表达过这样的观点. 在2021年百度世界大会上,小度又一口气发布了四款 ...

  10. windows许可证更新

    slmgr /ipk 许可证 slmgr /skms  服务器(kms.xspace.in) slmgr /ato 查看许可证 slmgr /xpr