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. Vtune工具简介

    VTune是 Intel 提供的一个强大的应用程序性能分析软件,VTune Amplifier XE 2011 集成了Intel VTune Performance Analyzer 和 Thread ...

  2. 内网渗透----使用mimikatz获取windows登陆口令

    使用mimikatz提取windows密码 以管理员运行后,可以随机打一些字符,进入如下界面 输入aaa::aaa,可展示所有模块: 可采用log命令,保存日志 获取hash与明文用户口令 privi ...

  3. loj536「LibreOJ Round #6」花札(二分图博弈)

    loj536「LibreOJ Round #6」花札(二分图博弈) loj 题解时间 很明显是二分图博弈. 以某个点为起点,先手必胜的充要条件是起点一定在最大匹配中. 判断方法是看起点到该点的边有流量 ...

  4. 什么是内部类? Static Nested Class 和 Inner Class的不同?

    内部类就是在一个类的内部定义的类,内部类中不能定义静态成员. 内部类作为其外部类的一个成员,因此内部类可以直接访问外部类的成员.但有一点需要指出:静态成员不能访问非静态成员,因此静态内部类不能访问外部 ...

  5. python 列表推导式,生成器推导式,集合推导式,字典推导式简介

    1.列表推导式multiples = [i for i in range(30) if i % 2 is 0]names = [[],[]]multiples = [name for lst in n ...

  6. 请说一说Servlet的生命周期?

    servlet有良好的生存期的定义,包括加载和实例化.初始化.处理请求以及服务结束.这个生存期由javax.servlet.Servlet接口的init,service和destroy方法表达. Se ...

  7. java-规约-集合

    /** * 1 * @hashCode&equals的处理: * 1-只要覆写了equals,必须复写hashCode. * 2-因为Set存储的是不重复的对象,依据hashCode和equa ...

  8. SpringBoot项目单元测试不经过过滤器问题

    SpringBoot使用MockMvc:https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-featu ...

  9. 客户端注册 Watcher 实现 ?

    1.调用 getData()/getChildren()/exist()三个 API,传入 Watcher 对象 2.标记请求 request,封装 Watcher 到 WatchRegistrati ...

  10. PN结

    摘自:https://blog.csdn.net/CPJ_phone/article/details/40979027                                          ...