首页 > 其他分享 >Tarjan学习笔记

Tarjan学习笔记

时间:2023-08-17 15:55:06浏览次数:35  
标签:Tarjan dfs int 连通 笔记 学习 dfn low 节点

Tarjan

Tarjan算法是图论中非常常用的算法之一,能解决强连通分量,双连通分量,割点和桥,求最近公共祖先(LCA)等问题。

Tarjan 算法是基于深度优先搜索的算法,用于求解图的连通性问题。

割点

如果从图中删除节点 \(x\) 以及所有与 \(x\) 关联的边之后,图将被分成两个或两个以上的不相连的子图,那么称 \(x\) 为图的割点。
image

如3、5就是图的割点

桥/割边

如果从图中删除边 \(e\) 之后,图将分裂成两个不相连的子图,那么称 \(e\) 为图的桥/割边。
image

如图中边 \((3,5)\) 就是图的割边

实现

几个定义

强连通分量 :
对于一个分量,若任意两个点相通,则称为强连通分量。

树边 :
对于一个图的dfs树,它的树边便是此图的树边。

返祖边 :
对于一个图的dfs树,可以使得儿子节点返回到它的祖先的边为返祖边。

横插边 :
对于一个图的dfs树,可以使得一个节点到达另一个节点且它们互不是祖先的边为横插边。

连通

连通:无向图中,从任意点 \(i\) 可到达任一点 \(j\) 。
强连通:有向图中,从任意点 \(i\) 可到达任一点 \(j\)。
弱连通:把有向图看作无向图时,从任意点i可到达任一点 \(j\)。
image

强连通分量

整个图并不是强连通的,但是在某些局部区域符合强连通的要求,如下图,整张图不算是强连通,但局部还是能满足强连通条件的。
image

时间戳

时间戳是用来标记图中每个节点在进行dfs时被访问的顺序,可以理解成一个由小到大的序号(类似于dfs序)。

搜索树

在无向图中,以某一个节点 \(x\) 出发进行dfs,每一个节点只访问一次,所有被访问过的节点和边构成一棵树,称之为“无向连通图的搜索树”。

追溯值

追溯值用来表示从当前节点 \(x\) 能够访问到的所有节点中,时间戳最小的值。
能够访问到的节点其需要满足下面的条件之一:

  • 以 \(x\) 为根的搜索树的所有节点。
  • 通过一条非搜索树上的边,能够到达搜索树的所有节点。

代码

dfn:第 \(i\) 个节点的时间戳。

low:第 \(i\) 个节点最多经过一条返祖边所能到达的最小时间戳。

s:一个栈,用来储存当前还未确定但已经扩展过的点。

b:第 \(i\) 个节点是否遍历过。

ans:答案计数。

void tarjan(int 当前点){
    这个点的low=dfn=时间戳;
    将这个点入栈;
    标记这个点入栈;
    for(这个点连接的所有边){
        if(目标点没有被访问过){
            tarjan(目标点);
            更新当前点的low; 
        }else if(目标点被访问过){
            更新当前点的low; 
        } 
    }
    if(当前点的low==dfn){
        将这个点及栈以上的点出栈,标记成一个强连通分量; 
        ans++; 
    } 
}
int dfn[100010],low[100010];
int n,m,num=0,ans=0;
vector<int>v[100010];
stack<int>s;
void tarjan(int x){
	num++;
    dfn[x]=low[x]=num;
    st.push(u);
    b[x]=1;
    for(int i=0;i<v[x].size();i++) {
        int nn=v[x][i];
        if(!dfn[nn]){
            tarjan(nn);
            low[x]=min(low[x],dfn[nn]);
        }else if(b[nn]){
        	low[x]=min(low[x],dfn[nn]);
		}
    }
    if(low[u]==dfn[u]){
    	while(!s.empty()&&s.top()!=u){
            vis[s.top()]=0;
            s.pop(); 
        }
        b[u]=0;
        s.pop();
        ans++;
	}
}

标签:Tarjan,dfs,int,连通,笔记,学习,dfn,low,节点
From: https://www.cnblogs.com/ccr-note/p/Tarjan.html

相关文章

  • go语言学习笔记摘要
    引用:https://learnku.com/docs/the-way-to-go/variable/3585摘要点:1.变量命名规则:变量的命名规则遵循骆驼命名法,即首个单词小写,每个新单词的首字母大写。2.变量赋值::=: 它只能被用在函数体内,而不可以用于全局变量的声明与赋值多变量可以在同一行进行赋值, ......
  • 【快应用】快应用广告学习之激励视频广告
    ​【关键词】快应用、激励视频广告、广告接入 【介绍】一、关于激励视频广告 定义:用户通过观看完整的视频广告,获得应用内相关的奖励。适用场景:游戏/快游戏的通关、继续机会、道具获取、积分等场景中,阅读、影音等应用的权益体系也有相关使用。支持格式:横版视频、竖版视......
  • 笔记整理--C语言--高质量C编程指南—林锐——转载
    高质量C编程指南—林锐头文件的作用略作解释:通过头文件来调用库功能。在很多场合,源代码不便(或不准)向用户公布,只要向用户提供头文件和二进制的库即可。用户只需要按照头文件中的接口声明来调用库功能,而不必关心接口怎么实现的。编译器会从库中提取相应的代码。头文件能加强......
  • 脚本学习:%cd%和%~dp0的区别
    在编写自动化脚本过程中,经常会需要获取当前目录路径。这里有两种方式,一种是%cd%,另一种是%~dp0,那么这两种方式有什么区别呢?今天就来具体讲一讲。具体含义%cd%:脚本执行的当前目录,需要注意的是,这里的当前目录有可能和脚本实际所在目录不一致。%~dp0%:脚本文件所在的目录,注意,目录的......
  • 极光笔记 | 如何为您的业务开发和训练一个AI-BOT
    生成式AI(GenerativeAI)是当今科技领域的前沿技术之一。随着数据量的不断增加和计算能力的不断提升,AI技术在企业和个人生活中的应用越来越广泛。AI-BOT(以下简称BOT)是生成式AI技术的其中一种重要的应用形式,它可以通过学习各类业务数据信息,帮助人们执行一系列任务,从而提高工作效率,减......
  • 笔记整理--C语言--sscanf()和sprintf()的用法总结——转载
    sscanf函数的高级用法sscanf与scanf类似,都是用于输入的,只是后者以屏幕(stdin)为输入源,前者以固定字符串为输入源。函数原型:intsscanf(constchar*format[,argument]...);其中的format可以是一个或多个:{%[*][width][{h|l|I64|L}]type|''|'\t'|'\n'|非%符号},注:*亦可用......
  • h5(html5)+css3前端笔记四
    Emmet语法1.生成标签直接输入标签名按tab键即可比如div然后tab键,就可以生成<div></div>2.如果想要生成多个相同标签加上*就可以了比如div*3就可以快速生成3个div3.如果有父子级关系的标签,可以用>比如ul>li就可以了4.如果有兄弟关系的标签,用+就可以了比如div+p5.如......
  • 极光笔记 | 如何为您的业务开发和训练一个AI-BOT
    生成式AI(GenerativeAI)是当今科技领域的前沿技术之一。随着数据量的不断增加和计算能力的不断提升,AI技术在企业和个人生活中的应用越来越广泛。AI-BOT(以下简称BOT)是生成式AI技术的其中一种重要的应用形式,它可以通过学习各类业务数据信息,帮助人们执行一系列任务,从而提高工作效率,减少......
  • QT学习——include《》和“”区别
    一、#include<>#include<>引用的是编译器的类库路径里面的头文件。假如你编译器定义的自带头文件引用在C:\Keil\c51\INC\下面,则#include<stdio.h>引用的就是C:\Keil\c51\INC\stdio.h这个头文件,不管你的项目在什么目录里,C:\Keil\c51\INC\stdio.h这个路径就定......
  • PHP反序列化漏洞笔记(一):初识序列化
    PHP类与对象类:一组共享相同结构和和行为的对象集合对象:类的实例使用new的关键字Phpmagic函数在PHP中,魔术方法(MagicMethods)是一组特殊的函数,它们以双下划线(__)作为前缀来命名。这些函数在特定的情况下会自动调用,以执行一些特定的操作。以下是一些常用的魔术方法:实践:自动化的操作:......