当前位置: 首页 > news >正文

算法学习笔记(Tarjan)

本文介绍 T a r j a n Tarjan Tarjan求强联通分量、找割点和割边、找环。

Tarjan求强联通分量

例题:【模板】有向图缩点

题目描述

给定一个 n n n m m m边的有向图(保证不存在重边与自环,但不保证连通),请你求出其中所有“大小大于 1 1 1”的强联通分量的大小,如果不存在则输出 − 1 −1 1

将所有强联通分量大小按从小到大顺序输出。

输入描述

第一行两个整数 n , m n,m n,m ( 1 ≤ n , m ≤ 2 × 1 0 5 ) (1 \leq n,m \leq 2 \times 10^5) (1n,m2×105)

接下来 m m m行,每行一条边 ( x , y ) (x,y) (x,y),表示存在一条由点 x x x到点 y y y的边。 ( 1 ≤ x , y ≤ n ) (1≤x,y≤n) (1x,yn)

输出描述

一行从小到大输出所有“大小大于 1 1 1”的强联通分量的大小,若不存在则输出 − 1 −1 1

输入样例1

4 4
1 2
2 3
3 1
1 4

输出样例1

3

强连通:在有向图 G G G中,如果两个点 u u u v v v是互相可达的,即从 u u u出发可以到达 v v v,从 v v v出发可以到达 u u u,则称 u u u v v v是强连通的。如果 G G G中任意两个点都是互相可达的,称 G G G是强连通图。

强连通分量(SCC):如果一个有向图 G G G不是强连通图,那么可以把它分成多个子图,其中每个子图的内部是强连通的,而且这些子图已经扩展到最大,不能与子图外的任意点强连通,称这样的一个“极大强连通”子图是 G G G的一个强连通分量。

接下来说明一个定理: S C C SCC SCC,从其中任意一个点出发,都至少有一条路径能绕回到自己。

明白这点之后,解释一下 T a r j a n Tarjan Tarjan求强连通分量的流程。

首先对于每一个节点,都有两个量: d f n dfn dfn l o w low low d f n dfn dfn表示该节点的 d f s dfs dfs序, l o w low low则表示该节点能返回到的最远祖先(对图跑 d f s dfs dfs生成搜索树,树上节点有祖先),初始时 l o w low low就等于自己的 d f s dfs dfs序,在之后更新的时候,有两种情况可以更新 l o w low low的值。一种是一个节点有一条有向边指向自己在搜索树上的祖先时,比较自己的 l o w low low和被访问到的祖先的 d f n dfn dfn,将自己的 l o w low low更新为两者中的最小值。还有一种情况就是 d f s dfs dfs回溯时,比较自己的 l o w low low和儿子的 l o w low low,将自己的 l o w low low更新为两者中的较小值。更新完回来之后,回到 d f n = l o w dfn = low dfn=low的点,作为强连通分量的根。将刚刚修改过 l o w low low值的点收拢,作为一个强连通分量。

特殊的,如果一个点有一条有向边指向了一个强连通分量,那么我们不应该去更新它的 l o w low low

为了区别这种情况,我们会使用栈来分离不同的 S C C SCC SCC,每访问一个点就将点丢入栈中,而每找出一个 S C C SCC SCC,则将这个 S C C SCC SCC中的所有点从栈中弹出。之后有边指向这个 S C C SCC SCC则不再理会(指向的点不在栈中说明已经属于一个 S C C SCC SCC)。

时间复杂度为: O ( n + m ) O(n + m) O(n+m)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 9, T = 20;vector<int> g[N];int dfn[N], low[N], stk[N], top, idx;
int tot, cnt[N];
bitset<N> ins;//tarjan的本质是dfs
void tarjan(int x)
{//1.初始化dfn和lowdfn[x] = low[x] = ++ idx;//2.入栈并标记stk[++ top] = x;ins[x] = true;//3.遍历所有儿子for(const auto &y : g[x]){//判断是否是回点if(!dfn[y]){tarjan(y);low[x] = min(low[x], low[y]);}else if(ins[y]) low[x] = min(low[x], dfn[y]);}//4.收拢if(low[x] == dfn[x]){//新开一个颜色tot ++;while(stk[top + 1] != x){//计数cnt[tot] ++;//取消标记ins[stk[top --]] = false;}}
}void solve()
{int n, m;cin >> n >> m;for(int i = 1;i <= m; ++ i){int x, y;cin >> x >> y;g[x].push_back(y);}for(int i = 1;i <= n; ++ i)if(!dfn[i])tarjan(i);vector<int> v;for(int i = 1;i <= tot; ++ i)if(cnt[i] > 1)v.push_back(cnt[i]);if(v.size()){sort(v.begin(), v.end());for(const auto &i : v)cout << i << ' ';}else cout << -1 << '\n';
}
int main()
{ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);int _ = 1;while(_ --)solve();return 0;
}

Tarjan求割点和割边

例题:【模板】无向图求割点、割边

题目描述

给一个 n n n m m m边的无向图(无重边与自环),请求出图中所有割点和割边的数量。

输入描述

第一行两个整数 n , m n,m n,m ( 1 ≤ n , m ≤ 2 × 1 0 5 ) (1 \leq n,m \leq 2 \times 10^5) (1n,m2×105)

接下来 m m m行,每行两个整数 x , y x,y x,y表示一条 x x x y y y之间的双向边。 ( 1 ≤ x , y ≤ n ) (1 \leq x,y \leq n) (1x,yn)

输出描述

一行两个整数,表示割点和割边的数量。

输入样例1

4 4
1 2
3 2
2 4
1 3

输出样例1

1 1

解释

割点为 2 2 2,割边为 2 − 4 2−4 24


割点和割边:无向图中所有能互通的点组成了一个“连通分量”。在一个连通分量中有一些关键的的点,如果删除它们,会把这个连通分量断开分为两个或更多,这种点称为割点。同样的,如果在一个连通分量中删除一条边,把这个连通分量分成了两个,这条边称为割边。

对于一个点:分两种情况,一是不作为搜索树的根的节点,只要在由这个节点的儿子中,有一个节点不连通到该节点的祖先( l o w [ y ] ≥ d f n [ x ] low[y] \geq dfn[x] low[y]dfn[x]),那么这个节点是割点(由该节点作为分界线,分割了它的儿子做根的子树和它的父亲)。二是作为搜索树的根的节点,需要两个儿子不连通到该节点( l o w [ y ] ≥ d f n [ x ] low[y] \geq dfn[x] low[y]dfn[x]),那么这个节点是割点(删除这个根,两棵子树就被分离开来了)。

而对于一条边,只要后边的点回不到前边的点( l o w [ y ] ≥ d f n [ x ] low[y] \geq dfn[x] low[y]dfn[x]),那么这个点就是割边。

那么计算割点割边只需要看是否满足上述条件就行。

#include <bits/stdc++.h>
#include <assert.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 9;vector<int> g[N];int dfn[N], low[N], idx, cut, es;void tarjan1(int x, int fa)
{dfn[x] = low[x] = ++ idx;int child = 0;for(const auto &y: g[x]){//1.不走父亲if(y == fa)continue;//2.判断是否是搜索树的儿子if(!dfn[y]){tarjan1(y, x);low[x] = min(low[x], low[y]);child += (low[y] >= dfn[x]);}else low[x] = min(low[x], dfn[y]);}if((!fa && child >= 2) || (fa && child >= 1))cut ++;
}void tarjan2(int x, int fa)
{dfn[x] = low[x] = ++ idx;for(const auto &y : g[x]){if(y == fa)continue;//如果y没被走过,就往下走if(!dfn[y]){//此时y是x在搜索树中的儿子tarjan2(y, x);low[x] = min(low[x], low[y]);//如果y回不到自身以及父亲树上if(low[y] > dfn[x])es ++;}else low[x] = min(low[x], dfn[y]);}
}set<pair<int, int> > st;void solve()
{int n, m;cin >> n >> m;for(int i = 1;i <= m; ++ i){int x, y;cin >> x >> y;g[x].push_back(y);g[y].push_back(x);}for(int i = 1;i <= n; ++ i)if(!dfn[i])tarjan1(i, 0);for(int i = 1;i <= n; ++ i)dfn[i] = low[i] = 0;idx = 0;for(int i = 1;i <= n; ++ i)if(!dfn[i])tarjan2(i, 0);cout << cut << ' ' << es << '\n';
}
int main()
{ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);int _ = 1;while(_ --)solve();return 0;
}

Tarjan找环

例题:【模板】Tarjan找环

题目描述

给定一个 n n n n n n边的无向连通图(不含重边与自环),请你求出图中环的大小。

可以证明图中存在且仅存在一个环。

输入描述

第一行一个整数表示测试样例数量 T T T ( 1 ≤ T ≤ 1000 ) (1 \leq T \leq 1000) (1T1000)

对于每组测试样例,第一行一个整数 n n n ( 1 ≤ n ≤ 2 × 1 0 5 ) (1 \leq n \leq 2 \times 10^5) (1n2×105)

接下来 n n n行,每行一条无向边 u , v u,v u,v ( 1 ≤ u , v ≤ n ) (1 \leq u,v \leq n) (1u,vn)

输出描述

对于每组测试样例,输出一个整数表示环的大小。

输入样例1

2
5
1 2
1 3
2 3
3 4
4 5
4
1 2
2 3
3 4
1 4

输出样例1

3
4

对于找环,找出一个强连通分量就是环。因为 n n n n n n边,一定存在且仅存在一个环(一棵树 n − 1 n - 1 n1条边,多连一条边必定生成一个环)。于是只要在找强连通分量的代码上稍加修改就行。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 9;vector<int> g[N];int dfn[N], low[N], idx, ans;
int stk[N], top;
bitset<N> ins;void tarjan(int x, int fa)
{dfn[x] = low[x] = ++ idx;stk[++ top] = x;ins[x] = true;for(const auto &y : g[x]){if(y == fa)continue;if(!dfn[y]){tarjan(y, x);low[x] = min(low[x], low[y]);}else if(ins[x])low[x] = min(low[x], dfn[y]);}if(low[x] == dfn[x]){int cnt = 0;while(stk[top + 1] != x){cnt ++;ins[stk[top --]] = false;}if(cnt > 1){ans = cnt;return;}}}void solve()
{int n;cin >> n;for(int i = 1;i <= n; ++ i){g[i].clear();stk[i] = dfn[i] = low[i] = 0;ins[i] = false;}stk[n + 1] = 0;ans = idx = top = 0;for(int i = 1;i <= n; ++ i){int x, y;cin >> x >> y;g[x].push_back(y);g[y].push_back(x);}tarjan(1, 0);cout << ans << '\n';
}
int main()
{ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);int _;cin >> _;while(_ --)solve();return 0;
}

T a r j a n Tarjan Tarjan找环应该只使用于 n n n n n n边的情况?)

相关文章:

算法学习笔记(Tarjan)

本文介绍 T a r j a n Tarjan Tarjan求强联通分量、找割点和割边、找环。 Tarjan求强联通分量 例题&#xff1a;【模板】有向图缩点 题目描述 给定一个 n n n点 m m m边的有向图&#xff08;保证不存在重边与自环&#xff0c;但不保证连通&#xff09;&#xff0c;请你求出…...

一台linux通过另一台linux访问互联网-TinyProxy

参考&#xff1a; https://blog.csdn.net/weixin_41831919/article/details/113061317https://www.yuncongz.com/archives/1.htmlhttps://blog.csdn.net/aoc68397/article/details/101893369 环境&#xff1a;ubuntu 18.04 机器1: IP 219.216.65.252 (可以访问外网) 机器2: IP…...

探索数据结构:堆的具体实现与应用

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;数据结构与算法 贝蒂的主页&#xff1a;Betty’s blog 1. 堆的概念 堆(Heap)是计算机科学中一类特殊的数据结构。堆通常是一个…...

网络2--MAC地址,IP地址的理解

引入&#xff1a; 每一张主机都会有一张网卡&#xff0c;每一张网卡都有一个48bit位的序列号 当我们的热点被连上&#xff0c;你查看时&#xff0c;就会出现MAC地址&#xff0c;IP地址 那么他们两个是什么呢&#xff1f;&#xff1f;&#xff1f; MAC地址 在同一个局域网中…...

类型的转换

首先我们要了解java中的数据类型转换是指将一种数据类型转换成另一种数据类型的过程。 什么时候会用到&#xff1f;我觉得两种情况会用到 等号左右两边类型不一致&#xff08;一般发生在赋值时&#xff09;不同类型的数据参与运算&#xff08;一般发生在计算时&#xff09; 转…...

memset函数

让我们先看两个代码 memset(dp, 0x3f, sizeof(dp)); for (int i 0; i < 5; i)cout << dp[i] << " "; memset(dp, 127, sizeof(dp)); for (int i 0; i < 5; i)cout << dp[i] << " "; 代码结果如下&#xff1a; 现在我们来分…...

Java面向对象——多态

即同一个方法可以根据发送对象的不同而采用多种不同的行为方式。 一个对象的实际类型是确定的&#xff0c;但可以指向对象的引用的类型有很多&#xff08;父类&#xff0c;有关系的类&#xff09;。 多态存在的条件&#xff1a; 1. 有继承关系&#xff1b; 2. 子类重写父类…...

python 对矩阵与矩阵之间对应位置的元素,做softmax操作,代码实战

1.对矩阵中对应位置的元素&#xff0c;做softmax 对于一个向量&#xff0c;softmax函数会对其中每一个元素进行指数运算&#xff0c;然后除以所有元素指数和的结果。当将其应用到多个矩阵的相应位置上时&#xff0c;我们实际上是在对每个位置的一组数&#xff08;从各个矩阵的同…...

Angular前端项目在Apache httpd服务器上的部署

Apache Httpd和Tomcat主要区别&#xff1a;Tomcat是一个Java Servlet容器&#xff0c;用于运行Java Servlet和JavaServer Pages&#xff08;JSP&#xff09;&#xff0c;而Apache HTTP服务器是一个通用的Web服务器&#xff0c;用于提供静态和动态内容。 Apache httpd安装&#…...

Oracle 更改数据文件位置的几种常用方式

Oracle 更改数据文件位置的几种常用方式 A.归档模式下 1、offline 表空间&#xff1a;alter tablespace tablespace_name offline&#xff1b; 2、复制数据文件到新的目录&#xff1b; 3、rename 修改表空间&#xff0c;并修改控制文件&#xff1b; 4、online 表空间&#xf…...

【opencv】图像畸变校正

接上篇文章&#xff1a;【鱼眼&#xff0b;普通相机】相机标定 附代码&#xff1a; 方法一&#xff1a; 使用cv2.undistort """Create May 11, 2024author Wang Jiajun """import cv2 import numpy as npdef correct(img,camera_fileE:/cali…...

Charger之二输入电压动态电源原理(VIN-DPM)

主要内容 Charger的VIN-DPM 前篇内容&#xff1a;电池管理IC&#xff08;Charger&#xff09;了解一下&#xff1f; 领资料&#xff1a;点下方↓名片关注回复&#xff1a;粉丝群 正文 一、 VIN-DPM概念 VIN-DPM是指输入电压动态电源管理&#xff08;Input voltage dynamic…...

【半夜学习MySQL】表结构的操作(含表的创建、修改、删除操作,及如何查看表结构)

&#x1f3e0;关于专栏&#xff1a;半夜学习MySQL专栏用于记录MySQL数据相关内容。 &#x1f3af;每天努力一点点&#xff0c;技术变化看得见 文章目录 创建表查看表结构修改表删除表 创建表 语法&#xff1a; create table table_name(field1 datatype,field2 datatype,fiel…...

曲线救国:window 安装 docker

你好&#xff0c;我是 shengjk1&#xff0c;多年大厂经验&#xff0c;努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注&#xff01;你会有如下收益&#xff1a; 了解大厂经验拥有和大厂相匹配的技术等 希望看什么&#xff0c;评论或者私信告诉我&#xff01; 文章目录 一…...

番外篇 | 利用PyQt5+YOLOv5来搭建目标检测系统(附可视化界面+功能介绍+源代码)

前言:Hello大家好,我是小哥谈。PyQt5是一个Python绑定的Qt库,是用于创建图形用户界面(GUI)和其他应用程序组件的工具包。PyQt5提供了许多GUI元素,如按钮、文本框、标签等,也提供了许多Qt的功能,如网络、数据库、XML等。通过PyQt5可以在Python中使用Qt的丰富功能和强大的工…...

Pascal Content数据集

如果您想使用Pascal Context数据集&#xff0c;请安装Detail&#xff0c;然后运行以下命令将注释转换为正确的格式。 1.安装Detail 进入项目终端 #即 这是在我自己的项目下直接进行克隆操作&#xff1a; git clone https://github.com/zhanghang1989/detail-api.git $PASCAL…...

【Unity】使用Resources.LoadAll读取文件的顺序问题

最近在做客户的一个项目&#xff0c;其中的一个模块使用到了照片&#xff0c;但是发现了一个很严重的问题。当你在使用Unity的时候&#xff0c;它竟然不按照顺序读取&#xff1f;这个机器人是不是逻辑有问题&#xff1f;如下图&#xff1a; 名字脱敏了哈。。。 照片比较多&…...

pdf怎么标注红色方框?五种PDF标注红色方框方法

pdf怎么标注红色方框&#xff1f;在当今数字化时代&#xff0c;PDF文档已成为我们日常工作和学习中不可或缺的一部分。然而&#xff0c;如何在海量的PDF文件中快速、准确地标注出重要信息&#xff0c;让内容更加醒目呢&#xff1f;今天&#xff0c;我将向大家介绍五种PDF标注红…...

C++字符串细节,面试题06

文章目录 22. 字符串22.1. 字符数组 vs 字符指针 vs 常量字符指针 vs string22.2. strcpy vs sprintf vs memcpy22.3. strlen vs length vs size vs sizeof22.4. 字符串之间的转换22.5 其他数据类型与字符串之间的转换22.6 字符串分割 22. 字符串 22.1. 字符数组 vs 字符指针 …...

AutoModelForCausalLM.from_pretrained 函数调用本地权重报错

文章目录 1、代码报错的位置&#xff08;前情提要&#xff09;finetune_lora.shfintune_clm_lora.py 2、报错截图2.1、huggingfaces上的 meta-llama/Llama-2-7b-chat-hf2.2、服务器上模型文件路径 3、特别注意事项 1、代码报错的位置&#xff08;前情提要&#xff09; 在终端直…...

独家披露:Perplexity未公开的政治新闻过滤白名单(含6国政府通报接口绕过逻辑与合规使用边界)

更多请点击&#xff1a; https://kaifayun.com 第一章&#xff1a;Perplexity政治新闻查询的底层机制与合规边界 Perplexity 在处理政治新闻类查询时&#xff0c;并非直接抓取或缓存原始新闻页面&#xff0c;而是依托其混合检索架构——融合实时网络搜索&#xff08;通过 Bing…...

【实操经验】拒答能力不达标,大模型备案怎么过

在生成式 AI 监管趋严的 2026 年&#xff0c;拒答率≥95% 是大模型备案的硬性门槛&#xff08;GB/T 45644-2025&#xff09;。不少自研或二次开发模型因安全对齐不足、拒答逻辑薄弱&#xff0c;测试时频繁 “翻车”—— 敏感问题答非所问、违法指令直接执行、多轮诱导轻易妥协&…...

超越跑分:深入CoreMark源码,看它如何“拷问”RISC-V CPU的三大核心能力

超越跑分&#xff1a;深入CoreMark源码&#xff0c;看它如何“拷问”RISC-V CPU的三大核心能力 在嵌入式处理器性能评估领域&#xff0c;CoreMark早已成为行业标准测试工具。但大多数开发者仅关注最终得分&#xff0c;却鲜少探究这个不足3000行代码的基准测试程序如何精准"…...

从游戏地图切割到3D模型生成:凸多边形三角剖分在Unity/C++中的实战应用

从游戏地图切割到3D模型生成&#xff1a;凸多边形三角剖分在Unity/C中的实战应用 在游戏开发中&#xff0c;我们经常需要处理复杂的几何形状。无论是为开放世界游戏创建导航网格&#xff0c;还是为3D模型生成优化的三角面片&#xff0c;凸多边形的三角剖分都是核心技能之一。不…...

Java反射getMethods()方法顺序不确定性解析与解决方案

1. 项目概述&#xff1a;一个看似简单却暗藏玄机的API行为如果你写过Java反射相关的代码&#xff0c;大概率用过Class.getMethods()这个方法。它的官方文档描述简洁明了&#xff1a;“返回一个包含 Method 对象的数组&#xff0c;这些对象反映了此 Class 对象表示的类或接口的所…...

CANN/asc-devkit:int64转half精度函数

__ll2half_ru 【免费下载链接】asc-devkit 本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言&#xff0c;原生支持C和C标准规范&#xff0c;主要由类库和语言扩展层构成&#xff0c;提供多层级API&#xff0c;满足多维场景算子开发诉求。 项目地址: https://gitcode.c…...

Python OAuth终极指南:requests-oauthlib快速入门与实战

Python OAuth终极指南&#xff1a;requests-oauthlib快速入门与实战 【免费下载链接】requests-oauthlib OAuthlib support for Python-Requests! 项目地址: https://gitcode.com/gh_mirrors/re/requests-oauthlib &#x1f510; Python OAuth认证是现代Web开发中不可或…...

不只是YOLOv5!详解Windows‘页面文件太小’错误的通用解决思路与内存优化技巧

不只是YOLOv5&#xff01;详解Windows‘页面文件太小’错误的通用解决思路与内存优化技巧 当你在深夜赶工一个重要的机器学习项目&#xff0c;或是渲染一段4K视频时&#xff0c;突然弹出一个冰冷的错误提示&#xff1a;"页面文件太小&#xff0c;无法完成操作"。这一…...

GNSS模块教程:大夏龙雀 DX-GP21,从硬件接线到 NMEA 数据解析

在物联网、无人机、精准农业等场景中&#xff0c;高精度定位是核心需求。深圳大夏龙雀科技的 DX-GP21 作为一款多模多频 GNSS 模块&#xff0c;支持北斗、GPS、Galileo 等多系统联合定位&#xff0c;定位精度&#xff1c;1.0m&#xff0c;兼具低功耗、小尺寸特性&#xff0c;性…...

VSCode Mermaid Preview:面向技术团队的实时图表协作解决方案

VSCode Mermaid Preview&#xff1a;面向技术团队的实时图表协作解决方案 【免费下载链接】vscode-mermaid-preview Previews Mermaid diagrams 项目地址: https://gitcode.com/gh_mirrors/vs/vscode-mermaid-preview 在技术文档编写、系统架构设计和项目规划过程中&…...