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的前辈,不满足该性质。

来自割点详解_zsyz_ZZY的博客-CSDN博客_割点

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的更多相关文章

  1. 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 ...

  2. 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 ...

  3. 2021.05.03 T3 数字

    2021.05.03 T3 数字 问题描述 一个数字被称为好数字当他满足下列条件: 1. 它有**2*n**个数位,n是正整数(允许有前导0) 2. 构成它的每个数字都在给定的数字集合S中. 3. 它 ...

  4. Noip模拟53 2021.9.14

    T1 ZYB和售货机 首先这道题有两种做法. 一种是发现每个点都可以先被取到只剩一个,只要收益大于$0$ 然后发现建一个$i->f[i]$的图时出现环,要把它去掉, 那么跑一个$tarjan$枚 ...

  5. 寻找大学目标及行动步骤——记ITAEM团队第二期宣讲会(2014.05.14)

    ·昨晚8:00-9:40.在 钟海楼03029 ,进行了ITAEM团队第二期宣讲会(第一期见第一期宣讲会总结).来參加的主要是大一学生.以信院为主.也有法学院.文学院的同学. 在宣讲会中,大家都比較积 ...

  6. OpenSpiel 随笔 05.14

    ------------恢复内容开始------------ 这两天年总算把自己的游戏写完了,也通过了所有的测试. 我将自己的代码上传到了我的github上, 地址是 https://github.c ...

  7. Noip模拟76 2021.10.14

    T1 洛希极限 上来一道大数据结构或者单调队列优化$dp$ 真就没分析出来正解复杂度 正解复杂度$O(q+nm)$,但是据说我的复杂度是假的 考虑一个点转移最优情况是从它上面的一个反$L$形转移过来 ...

  8. Noip模拟39 2021.8.14

    T1 打地鼠 都切掉了的简单题 1 #include<bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 con ...

  9. Noip模拟15 2021.7.14

    T1 夜莺与玫瑰 题目越发的变态起来... 这题刚开始看超级像仪仗队,好不容易码完欧拉函数后尝试×2后输出但不对!! 于是选择了跳过.... 正解居然是莫比乌斯函数....我也是醉了 预处理完就剩下$ ...

随机推荐

  1. 超详细GoodSync11.2.7.8单机、两个服务器之间的文件同步使用教程

    GoodSync安装教程 第一步:双机GoodSync_v11.2.7.8.exe文件 链接:https://pan.baidu.com/s/16FVater4f9vu07QiGGIK9A 提取码:b ...

  2. 14图像边缘检测的sobel_ctrl控制模块

    一设计功能 计算得到的dxy,再通过和阈值比较大小,输出po_sum作为VGA的输入,在显示器器上显示图像的轮廓. 二设计思路 根据前一篇博客对sobel算法的介绍,先通过FIFO的双流水线操作采集到 ...

  3. [bzoj3809]Gty的二逼妹子序列/[bzoj3236][Ahoi2013]作业

    [bzoj3809]Gty的二逼妹子序列/[bzoj3236][Ahoi2013]作业 bzoj   bzoj 题目大意:一个序列,m个询问在$[l,r]$区间的$[x,y]$范围内的数的个数/种类. ...

  4. Rust-Sqlx极简教程

    简介 sqlx 是 rust 中的一个数据库访问工具.具有以下特点: 异步:原生就支持异步,在并发性高的场合能够得到更好的支持 编译时检查查询:sqlx可以在 cargo build 的时候检查执行s ...

  5. 数据结构 - 顺序表 C++ 实现

    顺序表 此处实现的顺序表为**第一个位置为 data[0] **的顺序表 顺序表的定义为 const int MAX = 50; typedef int ElemType; typedef struc ...

  6. springboot实现热部署的几种方式

    原理:使用了两个ClassLoader,一个Classloader加载那些不会改变的类(第三方Jar包),另一个ClassLoader加载会更改的类,称为restart ClassLoader,这样在 ...

  7. 使用 rabbitmq 的场景?

    1.服务间异步通信 2.顺序消费 3.定时任务 4.请求削峰

  8. SublimeText 建立构建Node js系统

    Sublime Text 3 构建系统:https://www.sublimetext.com/docs/3/build_systems.html 注意: 文档中出现的 shell_cmd 和 cmd ...

  9. springboot 指定启动环境

    java -jar dbmaster.jar --spring.profiles.active=test

  10. Effective Java —— 用私有构造器或枚举类型强化单例属性

    本文参考 本篇文章参考自<Effective Java>第三版第三条"Enforce the singleton property with a private construc ...