模板Tarjan

news/2024/12/22 21:41:41/文章来源:https://www.cnblogs.com/abnormal123/p/18622612

Tarjan 模板

因为每次写Tarjan都会写挂,所以整理了一些模板。主要的证明就跳过了,主要区分不同模板的差异。

有向图和无向图

有向图和无向图的实现有时候会有区别,因为建出DFS树之后,有向图可能有横叉边,但是无向图不会(显然),所以有些细节需要注意。而且无向图判重边会比较麻烦。

无向图
void Tarjan(int u,int rt){dfn[u]=low[u]=++num;st.push(u);for(int i=head[u];i;i=e[i].nxt){int v=e[i].to;if(!dfn[v]){Tarjan(v,rt);low[u]=min(low[u],low[v]);}else low[u]=min(low[u],dfn[v]);}
}
有向图
void Tarjan(int u,int rt){dfn[u]=low[u]=++num;st.push(u);vis[u]=1;for(int i=head[u];i;i=e[i].nxt){int v=e[i].to;if(!dfn[v]){Tarjan(v,rt);low[u]=min(low[u],low[v]);}else if(vis[v]) low[u]=min(low[u],dfn[v]);}
}

可以看到,有向图较无向图只多了一个vis记录某节点是否在栈中,因为在栈中的节点都是当前节点在DFS树上的祖先节点,这样可以排除横叉边干扰。

割点/点双连通分量(无向图)

cut表示割点,scc表示点双包含的元素。一个点可以属于多个点双。(实际上只有割点可以)

求割点和点双本质上是一样的,判断条件:$ low[v]=dfn[u] $

网上存在两种写法,详见代码。

void Tarjan(int u,int rt){dfn[u]=low[u]=++tot;st.push(u);for(int i=head[u];i;i=e[i].nxt){int v=e[i].to;if(!dfn[v]){son[u]++;Tarjan(v,rt);low[u]=min(low[u],low[v]);if(low[v]==dfn[u]){//也可写成low[v]>=dfn[u],但是需要下一行的特判cut[u]=1;//if(u!=rt||son[u]>1)cut[u]=1;num++;int k=0;do{k=st.top();scc[num].push_back(k);st.pop();}while(k!=v);scc[num].push_back(u);//当前节点也在点双中}}else low[u]=min(low[u],dfn[v]);}
}

割边/边双连通分量/强连通分量(无向图)

brige表示割边,dcc表示边双包含的元素。每个点只会属于一个边双。

相似求法,判断条件:$ low[v]<dfn[u] $

与割点几乎没有区别。唯一不好的是重边容易出错,原因?

由于是无向图,所以直接由父亲节点更新当前节点的low是不正确的,有重边例外。一个可行的实现是:记录一个vis为这条边是否遍历过,只能有未经过的边转移。(一个技巧,初始化cnt(链式前向星的边数)为1,这样 \(i\)\(i\ xor \ 1\) 就对应同一条边 )

void Tarjan(int u,int rt,int fa){dfn[u]=low[u]=++tot;st.push(u);for(int i=head[u];i;i=e[i].nxt){int v=e[i].to;if(!dfn[v]){vis[i]=vis[i^1]=1;Tarjan(v,rt,u);low[u]=min(low[u],low[v]);if(low[v]>dfn[u]){brige[e[i].id]=1;num++;int k=0;do{k=st.top();dcc[num].push_back(k);st.pop();}while(k!=v);}}else if(!vis[i]) low[u]=min(low[u],dfn[v]);}// if(dfn[u]==low[u]){// 	ans++;// 	int k=0;// 	do{// 		k=st.top();// 		dcc[ans].push_back(k);// 		st.pop();// 	}while(k!=u);// }// 求边双也可以写成这样,便于和缩点一起记忆
}

缩点(有向图)

缩点就是把一个强连通分量缩成一个点,使原图成为一个DAG。

void Tarjan(int u,int rt){dfn[u]=low[u]=++tot;st.push(u);vis[u]=1;for(int i=head[u];i;i=e[i].nxt){int v=e[i].to;if(!dfn[v]){Tarjan(v,rt);low[u]=min(low[u],low[v]);}else if(vis[v]) low[u]=min(low[u],dfn[v]);}if(low[u]==dfn[u]){int k=0;num++;do{k=st.top();scc[num].push_back(k);vis[k]=0;//注意清空visbel[k]=num;sum[num]+=val[k];st.pop();}while(k!=u);}
}

总结

我写过的差不多就这些,主体部分是相似的(也许这是为什么Tarjan总学不会),重点区分点双和边双的判断条件,有向图和无向图的处理细节。对于不同的写法记一种就够用了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/856956.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

离开Jetbrains拥抱VsCode: 离开大便拥抱大便

文章讨论了作者从Jetbrains转向VsCode的原因,主要集中在AI编程支持和个性化体验上。Jetbrains在AI Coding的支持方面表现不佳,如更新速度慢、功能不足等,使得作者感到不满;而Jetbrains自己开发的AI Assistant也未能提供满意的体验。相对而言,VsCode在插件系统和自由度上表…

第十一篇:下载网站与动态网站架构

视频下载网站网站名:视频下载网站 域名:video.download.cn 站点目录:/app/code/vide/ 需求:浏览器打开后,显示目录结构 增加svip认证功能 增加统计功能(统计nginx服务的访问等状态)autoindex模块 自动索引功能(列表站点目录的内容),首页文件不存在autoindex模块 说明…

P1438 无聊的数列

链接:https://www.luogu.com.cn/problem/P1438 题面:思路: 差分+线段树。 刚开始的想法是建立一个双tag线段树:basetag和addtag。然后传递的时候basetag就是l的基准,addtag不变。求的话就是求节点值。 但是这样容易溢出。。。 所以考虑差分:利用前缀和代替当前某一点的值…

2024.12.22

数学归纳法常用公式\((a+b)^n\) \((a+b)^n\)的系数是杨辉三角的某一层,a升幂排列,b降幂排列 同理可得\((a-b)^n\),可以看作(\(a+(-b))^2\),与上面相同。

【PHP安全】php程序源码保护技术

一、基本介绍二、加密方式2.1 源码混淆处理2.1.1 PHP 威盾混淆2.1.2 php-obfuscator2.2 YAK Pro混淆处理2.3 源码外壳加密2.3.1 PHP Eval加密2.3.2 PHP Eval变异2.3.3 phpjiami处理2.4 源码扩展加密2.4.1 php-beast2.4.2 Zend Guard文末小结一、基本介绍 PHP语言作为脚本语言的…

[长期活动] 【4Z-API】每5楼抽取1位送10美金API额度,20%中奖机会!

​ 活动详情 活动时间: 长期有效 奖励内容: 每5楼抽取1位幸运用户,送价值10美金API额度 ** 参与方式** 登录 4Z API域名巧记:ZZZZAPI.com 4个Z然后API 简单好记:4Z= ZZZZAPI.com 每5个楼层将抽取1位幸运用户4Z-API优势稳定高速的API服务超值定价,性价比之选7x24小时技术支持…

CW信号的正交解调

1.CW信号CW可以叫做等幅电报,它通过电键控制发信机产生短信号"."(点)和长信号"--"(划),并利用其不同组合表示不同的字符,从而组成单词和句子。CW信号可以看作一种幅度调制信号,类似于幅移键控(2ASK信号)其携带的信息保存在其幅度中,通过改变载波…

团队作业3

团队作业3--需求改进&系统设计这个作业属于哪个课程 https://edu.cnblogs.com/campus/gdgy/CSGrade22-34这个作业要求在哪里 https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/homework/13233这个作业的目标 修改完善需求规格说明书、系统设计、Alpha任务分配计划、测试计…

Authz0:自动化授权测试工具

免责声明 本文提供的资源仅供学习,利⽤本文所提供的信息而造成的任何直接或者间接的后果及损失,均由使⽤者本⼈负责,本文及作者不为此承担任何责任,一旦造成后果请自行承担责任!简介 Authz0 是一款自动化授权测试工具。可以根据URL和角色与凭证识别未经授权的访问。URL和角…

戴尔T3680工作站 改造虚拟工作站,满足多人设计需求

在戴尔 T3680 工作站作为通过了 NVIDIA vWS兼容性认证的工作站,部署 Proxmox VE 和 DoraCloud,可以实现工作站虚拟化,满足多个用户设计需求。可以顺畅运行 SolidWorks、NX/UG 等大型CAD软件。满足企业 资源共享、信息安全、远程设计的业务需求。最近拿到一台 戴尔 T3680 工作…

HDU3746-Cyclic Nacklace

继续跟着邝斌飞刷KMP HDOJ3746 百度的时候发现题目英语弄错了,项链英文是Necklace,不是Nacklace读完之后我滴妈,上难度了呀 题意:就是给你个字符串a~z,,###:妈逼的不知道咋回事百度那个搜索不知道是不是总更新网页html一些东西,ADblock拦截又tm不好使了,还得重新拦截。…

天嵌通途xczu15eg学习笔记——基于iwip的TCP服务器性能测试(一)

学习记录——基于iwip的TCP服务器性能测试(一) 环境如下,Windows10,vivado2020.2 硬件部分设置如下:PS-PL之间的交互时钟,复位已关闭 Generate Output Products,Create HDL Wrapper,Export Hardware之后进入vitis开发环境 选择IwIP TCP Perf Server模版 打开Terminal中的…