2021.05.14 tarjan
2021.05.14 tarjan
标准版tarjan
这里使用数组来模拟栈
void tarjan(int x){
++ind;
dfn[x]=low[x]=ind;
stacki[++top]=x;
instack[x]=true;
for(int i=head[x];i;i=a[i].next ){
int v=a[i].to ;
if(dfn[v]==0){
tarjan(v);
low[x]=min(low[x],low[v]);
}else if(instack[v]){
low[x]=min(low[x],dfn[v]);//此处可改为low[x]=min(low[x],low[v]);原因如下解释
}
//建议加上if(instacki[v]),否则不在栈中的元素且dfn已更新过的元素会被再一次更新
}
int k=0;
if(dfn[x]==low[x]){
++cnt;
do{
k=stacki[top];
--top;
++num[cnt];
instack[k]=false;
belong[k]=cnt;
}while(k!=x);
}
}
//luougu 2341
直接使用STL
void tarjan(int x){
++ind;
low[x]=dfn[x]=ind;
stacki.push(x);
vis[x]=1;
for(int i=head[x];i;i=a[i].next ){
int v=a[i].to ;
if(!dfn[v]){
tarjan(v);
low[x]=min(low[x],low[v]);
}else if(vis[v]){
low[x]=min(low[x],low[v]);//此处可改为low[x]=min(low[x],dfn[v]);
}
}
int k=0;
if(low[x]==dfn[x]){
do{
k=stacki.top();
stacki.pop() ;
vis[k]=0;
bl[k]=x;
}while(k!=x);
}
}
缩点
在找到每个点属于哪一个强连通分量以后再建一个图就成,以下为主要代码:
void addi(int u,int v){
++cnt;
ai[cnt].from =u;
ai[cnt].to =v;
ai[cnt].next =headi[u];
headi[u]=cnt;
++in[v];
}
void tarjan(int x){
++ind;
low[x]=dfn[x]=ind;
stacki.push(x);
vis[x]=1;
for(int i=head[x];i;i=a[i].next ){
int v=a[i].to ;
if(!dfn[v]){
tarjan(v);
low[x]=min(low[x],low[v]);
}else if(vis[v]){
low[x]=min(low[x],dfn[v]);
}
}
int k=0;
if(low[x]==dfn[x]){
do{
k=stacki.top();
stacki.pop() ;
vis[k]=0;
bl[k]=x;
sum[x]+=num[k];//题目需要,可删
}while(k!=x);
}
}
int main(){
//中间省略
for(int i=1;i<=n;i++){
if(!dfn[i])tarjan(i);
}
cnt=0;
for(int i=1;i<=m;i++){
if(bl[a[i].from ]!=bl[a[i].to ]){
addi(bl[a[i].from ],bl[a[i].to ]);
}
}
//中间省略
return 0;
}
//luogu 3387
割点
定义:在一个无向图中,如果去掉一个点和它所连出去的的所有边,使得剩下的点不联通(即分成一个以上的强连通分量)时,这个点被称为关节点。关节点也就是割点。
对于根节点:
如图1,当根节点只有一个儿子时,割掉它,剩下的点必然联通,且新的树的个节点为它的儿子;
如图2,当根节点有两个儿子时,割掉它,剩下的点必然不联通(有两个强连通分量)。
对于非根节点:
如图3,点v1,v2均为点u的儿子,我们可以发现(手动模拟,v1和v2不联通),点u为割点。
此时点u存在一个可遍历到的后代v1,且点v1无法走回点u的前辈,满足该性质。
我们在v1,v2间加上一条边。
如图4,此时我们可以发现点u并不为割点(此时v1,v2和点u的前辈联通)。
此时点u存在一个可遍历到的后代v1,且点v1,v2都可以走回点u的前辈,不满足该性质。
void tarjan(int x,int root){
int child=0;
++ind;
low[x]=dfn[x]=ind;
for(int i=head[x];i;i=a[i].next ){
int v=a[i].to ;
if(!dfn[v]){
tarjan(v,x);
low[x]=min(low[x],low[v]);
if(low[v]>=dfn[x]&&x!=root)cut[x]=1;
if(x==root)++child;
}
low[x]=min(low[x],dfn[v]);//此处不可以改为low[x]=min(low[x],low[v]);解释如下
}
if(root==x&&child>=2)cut[x]=1;
}
int main(){
//中间省略
for(int i=1;i<=n;i++)
if(!dfn[i])tarjan(i,i);
for(int i=1;i<=n;i++)
if(cut[i])++ans;
//中间省略
}
//luogu 3388
关于low[x]=min(low[x],low[v])和low[x]=min(low[x],dfn[x])的问题
标准版tarjan和缩点需要判断点在不在强连通分量中以及在哪个强连通分量中,所以一个点可以重复更新low[x]=min(low[x],dfn[v]),如果在同一个强连通分量中,迟早会遍历到起点,况且instacki[]或vis[]数组就是为了判断这个点在不在栈中。
而割点只需要寻到这个点能到达的且不是从来时的边到达的最早的节点,这个最早的节点可以和另一个更早的节点相连,设最早的节点为fa,更早的节点为grandpa,这个节点为son,则low[fa]==low[grandpa]&&dfn[fa]!=dfn[grandpa],我们只需要使low[son]=dfn[fa]而不是使low[x]=low[grandpa]。
参考题解 P3388 【【模板】割点(割顶)】 - Michael_Li 的博客 - 洛谷博客 (luogu.com.cn)
2021.05.14 tarjan的更多相关文章
- java selenium启动火狐浏览器报错:Cannot find firefox binary in PATH. Make sure firefox is installed. OS appears to be: VISTA Build info: version: '3.8.1', revision: '6e95a6684b', time: '2017-12-01T19:05:14.666Z
Cannot find firefox binary in PATH. Make sure firefox is installed. OS appears to be: VISTA Build in ...
- 2021.11.14 CF1583E Moment of Bloom(LCA+图上构造)
2021.11.14 CF1583E Moment of Bloom(LCA+图上构造) https://www.luogu.com.cn/problem/CF1583E 题意: She does h ...
- 2021.05.03 T3 数字
2021.05.03 T3 数字 问题描述 一个数字被称为好数字当他满足下列条件: 1. 它有**2*n**个数位,n是正整数(允许有前导0) 2. 构成它的每个数字都在给定的数字集合S中. 3. 它 ...
- Noip模拟53 2021.9.14
T1 ZYB和售货机 首先这道题有两种做法. 一种是发现每个点都可以先被取到只剩一个,只要收益大于$0$ 然后发现建一个$i->f[i]$的图时出现环,要把它去掉, 那么跑一个$tarjan$枚 ...
- 寻找大学目标及行动步骤——记ITAEM团队第二期宣讲会(2014.05.14)
·昨晚8:00-9:40.在 钟海楼03029 ,进行了ITAEM团队第二期宣讲会(第一期见第一期宣讲会总结).来參加的主要是大一学生.以信院为主.也有法学院.文学院的同学. 在宣讲会中,大家都比較积 ...
- OpenSpiel 随笔 05.14
------------恢复内容开始------------ 这两天年总算把自己的游戏写完了,也通过了所有的测试. 我将自己的代码上传到了我的github上, 地址是 https://github.c ...
- Noip模拟76 2021.10.14
T1 洛希极限 上来一道大数据结构或者单调队列优化$dp$ 真就没分析出来正解复杂度 正解复杂度$O(q+nm)$,但是据说我的复杂度是假的 考虑一个点转移最优情况是从它上面的一个反$L$形转移过来 ...
- Noip模拟39 2021.8.14
T1 打地鼠 都切掉了的简单题 1 #include<bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 con ...
- Noip模拟15 2021.7.14
T1 夜莺与玫瑰 题目越发的变态起来... 这题刚开始看超级像仪仗队,好不容易码完欧拉函数后尝试×2后输出但不对!! 于是选择了跳过.... 正解居然是莫比乌斯函数....我也是醉了 预处理完就剩下$ ...
随机推荐
- python写一个web目录扫描器
用到的模块urliib error #coding = utf-8 #web目录扫描器 by qianxiao996 #博客地址:https://blog.csdn.net/qq_36374896 i ...
- 添加ico图标
1. 先添加资源文件XXX.Ico,然后引用的时候用如下代码即可. Icon ico=Properties.Resources.XXX;
- json知识点总结(二)--JSONObject详解
JSONObject只是一种数据结构,可以理解为JSON格式的数据结构(key-value 结构),可以使用put方法给json对象添加元素.JSONObject可以很方便的转换成字符串,也可以很方便 ...
- 记录Markdown的学习
目录 1. 引言 2. 标题 这是一级标题 这是二级标题 这是三级标题 这是四级标题 3. 文字相关 3.1 粗体 3.2 斜体 3.3 粗体和斜体 3.4 删除线 3.5 混合使用 3.6 反引号引 ...
- 在idea中新建完springboot项目的时候遇到问题(右键没有class选择;控制台报错:Could not transfer artifact org.apache.tomcat.embed:tomcat-embed-core:jar:9.0.60 from/to central ....)
一.在idea中新建完springboot项目的时候遇到问题 问题1:右键没有class选择 解决:之所以会如此,是因为项目还没完成创建完成,解决:只需等等即可,等到完全创建完成即可 问题2(报tom ...
- 到底为什么不建议使用SELECT *?
"不要使用SELECT *"几乎已经成为了MySQL使用的一条金科玉律,就连<阿里Java开发手册>也明确表示不得使用*作为查询的字段列表,更是让这条规则拥有了权威的加 ...
- kafka分布式的情况下,如何保证消息的顺序?
作者:可期链接:https://www.zhihu.com/question/266390197/answer/772404605来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注 ...
- Oracle SQL Developer.exe双击启动错误信息dll未找到
下载地址:https://www.oracle.com/tools/downloads/sqldev-downloads.html 官网相应的解决方法已经说明了
- JVM原理与深度调优
什么是jvm jvm是java虚拟机 运行在用户态.通过应用程序实现java代码跨平台.与平台无关.实际上是"一次编译,到处执行" 1.从微观来说编译出来的是字节码!去到哪个平台都 ...
- PID控制算法的C语言实现
参考: PID控制器开发笔 浅谈位置式PID 专家PID控制在快速系统中的仿真及应用(这篇了论文介绍的积分分离PID.专家PID(脚本实现和simulink实现)很详细) PID控制算法的C语言实现一 ...