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

【图论】无向图连通性(tarjan算法)

割边:dfn[u]<low[v]

割点:dfn[u]<=low[v] (若为根节点,要有两个v这样的点)

一.知识点:

1.连通

在图论中,连通性是指一个无向图中的任意两个顶点之间存在路径。如果对于图中的任意两个顶点 u 和 v,存在一条路径从 u 到 v,那么图被称为连通图。如果图不是连通的,那么它可以被分为多个连通分量,每个连通分量都是一个连通子图。

2.割点:

割点(Cut Vertex),也称为关节点或割顶,是指在无向图中,如果移除该顶点及其相连的边,会导致图不再连通,那么该顶点就被称为割点。

3.割边:

割边(Cut Edge),也称为,是指在无向图中,如果移除该边,会导致图不再连通,那么该边就被称为割边。

割边在图中起到了连接不同连通分量的作用,其移除会导致图的连通性发生变化。

 4.tarjan算法:(选择性阅读)

 Tarjan算法是一种用于寻找有向图中强连通分量(Strongly Connected Components,简称SCC)的算法,由Robert Tarjan在1972年提出。强连通分量是指在有向图中,任意两个顶点之间存在双向路径。

Tarjan算法使用深度优先搜索(DFS)来遍历图,并通过维护一个栈和一些辅助数据结构来识别强连通分量。算法的基本思想是通过DFS遍历图中的每个顶点,并为每个顶点记录其访问次序(Discovery Time)和能够回溯到的最早的祖先顶点(Lowest Ancestor)。通过这些信息,可以识别出具有相同祖先的顶点集合,即一个强连通分量。

Tarjan算法的步骤如下:

  1. 对图中的每个顶点进行深度优先搜索(DFS)遍历。
  2. 在DFS遍历的过程中,为每个顶点记录其访问次序和最早祖先顶点。
  3. 将已访问的顶点入栈。
  4. 当DFS遍历回溯到一个顶点时,检查该顶点的最早祖先顶点。如果最早祖先顶点是自身,则将栈中的顶点弹出,并将这些顶点构成一个强连通分量。
  5. 重复步骤3和步骤4,直到遍历完所有的顶点。

Tarjan算法的时间复杂度为O(V+E),其中V是顶点数,E是边数。它是一种高效的算法,常被用于解决与强连通分量相关的问题,如图的缩点、强连通分量的数量和结构等。

总之,Tarjan算法是一种用于寻找有向图中强连通分量的算法,通过DFS遍历和栈的运用,可以高效地找到图中的所有强连通分量。


二.讲解 

在此之前,先介绍两个数组;

int dfn[];里面存放访问顺序(时间戳);

int low[];里面存放追溯值(即祖先节点最小的dfn)

(1)割边

tarjan提出:(证明可以自行百度)

当dfn[u]<low[v]时,连接这两条点的边为割边(重边要特殊处理,后面介绍)

(2)割点

tarjan提出:(证明可以自行百度)

当dfn[u]<=low[v]时,u这个点为割点(若为根节点,要有两个v这样符合条件的点)


三.割边

(1)题目

题目描述:

找出割边

输入:

第一行输入两个整数n和m,表示点和边的个数。

第i(2<=i<=2+m)行,每行输出两个数字,表示一条边的两个点。

输出:

割边

样例输入:

6 7
1 2
1 3
2 4 
2 5
3 4
4 5
4 6

样例输出:

4---6

(2)初代码 

/*
6 7
1 2
1 3
2 4 
2 5
3 4
4 5
4 6
*/#include<bits/stdc++.h>
#define maxn 100005
using namespace std;
int n,m;
struct Edge{int u,v,next;
}edge[maxn<<1];
int cnt,head[maxn];
void add(int u,int v){edge[++cnt]=(Edge){u,v,head[u]}; head[u]=cnt;
}
int num,dfn[maxn],low[maxn];
void tarjan(int u,int fa){dfn[u]=low[u]=++num;for(int i=head[u];i;i=edge[i].next){int v=edge[i].v;if(v==fa) continue;if(dfn[v]==0){tarjan(v,u);low[u]=min(low[u],low[v]);if(dfn[u]<low[v]){ //割边条件 ,若>则表示v不止和u相连 cout<<u<<"----"<<v<<endl; }}else{low[u]=min(low[u],dfn[v]);}}
}
int main(){scanf("%d%d",&n,&m);int u,v;for(int i=1;i<=m;i++){scanf("%d%d",&u,&v);add(u,v); add(v,u);}tarjan(1,0);return 0;
}

(3)bug与解答

1.若这张图有多个连通分量怎么办?

答:遍历即可

	for(int i=1;i<=n;i++){if(dfn[i]==0)  tarjan(1,0);}

2.若有重边怎么办?结果显然不对。

答:只continue,第二次让这段代码运行

然后就无法满足 dfn[u]<low[v]条件了

		if(v==fa){k++; //防止重边 if(k==1) continue;} 

(4)最终代码

/*
6 7
1 2
1 3
2 4 
2 5
3 4
4 5
4 6
*/#include<bits/stdc++.h>
#define maxn 100005
using namespace std;
int n,m;
struct Edge{int u,v,next;
}edge[maxn<<1];
int cnt,head[maxn];
void add(int u,int v){edge[++cnt]=(Edge){u,v,head[u]}; head[u]=cnt;
}
int num,dfn[maxn],low[maxn];
void tarjan(int u,int fa){int k=0;dfn[u]=low[u]=++num;for(int i=head[u];i;i=edge[i].next){int v=edge[i].v;if(v==fa){k++; //防止重边 if(k==1) continue;} if(dfn[v]==0){tarjan(v,u);low[u]=min(low[u],low[v]);if(dfn[u]<low[v]){ //割边条件 ,若>则表示v不止和u相连 cout<<u<<"---"<<v<<endl; }}else{low[u]=min(low[u],dfn[v]);}}
}
int main(){scanf("%d%d",&n,&m);int u,v;for(int i=1;i<=m;i++){scanf("%d%d",&u,&v);add(u,v); add(v,u);}//防止本来就有不连通的 for(int i=1;i<=n;i++){if(dfn[i]==0)  tarjan(1,0);}return 0;
}

四.割点

其实只是微改动一下即可。其次就是可以优化一下。函数传参只需要传u,无需判断是否为父节点。因为不会影响结果。(自行参考代码推理)

再次强调:若为根节点,要有两个v这样的点!

参考代码:

/*
6 7
1 2
1 3
2 4 
2 5
3 4
4 5
4 6
*/#include<bits/stdc++.h>
#define maxn 100005
using namespace std;
int n,m;
struct Edge{int u,v,next;
}edge[maxn<<1];
int cnt,head[maxn];
void add(int u,int v){edge[++cnt]=(Edge){u,v,head[u]}; head[u]=cnt;
}
int num,dfn[maxn],low[maxn],root;
void tarjan(int u){dfn[u]=low[u]=++num;int flag=0;for(int i=head[u];i;i=edge[i].next){int v=edge[i].v;if(dfn[v]==0){tarjan(v);low[u]=min(low[u],low[v]);if(dfn[u]<=low[v]){ //割点条件 if(u!=root || flag>1) cout<<u<<" ";}}else{low[u]=min(low[u],dfn[v]);}}
}
int main(){scanf("%d%d",&n,&m);int u,v;for(int i=1;i<=m;i++){scanf("%d%d",&u,&v);add(u,v); add(v,u);}//防止本来就有不连通的 for(int i=1;i<=n;i++){if(dfn[i]==0){root=i;tarjan(i);} }return 0;
}

相关文章:

【图论】无向图连通性(tarjan算法)

割边&#xff1a;dfn[u]<low[v] 割点&#xff1a;dfn[u]<low[v] (若为根节点&#xff0c;要有两个v这样的点) 一.知识点&#xff1a; 1.连通&#xff1a; 在图论中&#xff0c;连通性是指一个无向图中的任意两个顶点之间存在路径。如果对于图中的任意两个顶点 u 和 v&…...

Docker安装

Docker实践 yum安装 YUM源可以使用官方YUM源、清华大学开源镜像站配置YUM源&#xff0c;也可以使用阿里云开源镜像站提供的YUM源&#xff0c;建议选择使用阿里云开源镜像站提供的YUM源&#xff0c;原因速度快。 地址: https://developer.aliyun.com/mirror/ 我们安装ce版 …...

06. 计数原理

6. 计数原理 6.1 分类加法计数原理与分步乘法计数原理 分类加法计数原理定义 完成一件事&#xff0c;有 n n n 类办法&#xff0c;在第1类办法中有 m 1 m_1 m1​ 种不同的方法&#xff0c;在第2类办法中有 m 2 m_2 m2​ 种不同的方法&#xff0c;…&#xff0c;在第 n n…...

计算机网络基础(静态路由,动态路由,公网IP,私网IP,NAT技术)

文章目录 一&#xff1a;静态路由和动态路由二&#xff1a;静态路由的配置路由信息的方式演示三&#xff1a;默认路由四&#xff1a;公网IP和私网IP和NAT技术的基本理解 一&#xff1a;静态路由和动态路由 在说静态路由和动态路由前&#xff0c;我们需要来了解一下&#xff0…...

CGAL 点云Alpha-Shape曲面重建算法

文章目录 一、简介二、相关参数三、实现代码四、实现效果参考资料一、简介 在数学上, a l p h a − s h a p e alpha-shape a...

Java 文件过滤器FileFilter | 按条件筛选文件

文章目录 一、概述1.1 何时会用到文件过滤器1.2 工作流程1.3 常用的接口和类1.4 文件过滤器的作用 二、按文件属性过滤2.1 按前缀或后缀过滤文件名2.2 按文件大小过滤 三、按文件内容过滤3.1 文本文件过滤器3.1.1 根据关键字过滤文件内容3.1.2 使用正则表达式过滤文件内容 3.2 …...

python格式化地址信息

背景 最近在折腾一个好玩的库&#xff0c;capa 实现地址的格式化输出。我看的教程是这样的&#xff1a; location_str ["徐汇区虹漕路461号58号楼5楼", "泉州市洛江区万安塘西工业区"] import cpca df cpca.transform(location_str) df在正式的运行代码…...

k8s1.26.6 安装gitlab

Gitlab官方提供了 Helm 的方式在 Kubernetes 集群中来快速安装&#xff0c;但是在使用的过程中发现 Helm 提供的 Chart 包中有很多其他额外的配置&#xff0c;所以我们这里使用自定义的方式来安装&#xff0c;也就是自己来定义一些资源清单文件。 Gitlab主要涉及到3个应用&…...

C5.0决策树建立个人信用风险评估模型

通过构建自动化的信用评分模型&#xff0c;以在线方式进行即时的信贷审批能够为银行节约很多人工成本。本案例&#xff0c;我们将使用C5.0决策树算法建立一个简单的个人信用风险评估模型。 导入类库 读取数据 #创建编码所用的数据字典 col_dicts{} #要编码的属性集 cols [che…...

【k8s集群部署】使用containerd运行时部署kubernetes集群(V1.27版本)

【k8s集群部署】使用containerd运行时部署kubernetes集群(V1.27版本) 一、本次实践介绍1.1 环境规划介绍1.2 本次实践简介二、三台主机基础环境配置2.1 主机配置工作2.2 关闭防火墙和selinux2.3 关闭swap2.4 清空iptables2.5 配置时间同步2.6 修改内核参数2.7 配置hosts文件三…...

网络安全进阶学习第八课——信息收集

文章目录 一、什么是信息收集&#xff1f;二、信息收集的原则三、信息收集的分类1.主动信息收集2.被动信息收集 四、资产探测1、Whois查询#常用网站&#xff1a; 2、备案信息查询#常用网站&#xff1a; 3、DNS查询#常用网站&#xff1a; 4、子域名收集#常用网站&#xff1a;#常…...

Spring Data Elasticsearch - 在Spring应用中操作Elasticsearch数据库

Spring Data Elasticsearch 文章目录 Spring Data Elasticsearch1. 定义文档映射实体类2. Repository3. ElasticsearchRestTemplate3.1 查询相关特性3.1.1 过滤3.1.2 排序3.1.3 自定义分词器 3.2 高级查询 4. 索引管理4.1 创建索引4.2 检索索引4.3 修改映射4.4 删除索引 5. 异常…...

图论-简明导读

计算机图论是计算机科学中的一个重要分支&#xff0c;它主要研究图的性质和结构&#xff0c;以及如何在计算机上有效地存储、处理和操作这些图。本文将总结计算机图论的核心知识点。 一、基本概念 计算机图论中的基本概念包括图、节点、边等。图是由节点和边构成的数据结构&am…...

记一次 .NET 某物流API系统 CPU爆高分析

一&#xff1a;背景 1. 讲故事 前段时间有位朋友找到我&#xff0c;说他程序CPU直接被打满了&#xff0c;让我帮忙看下怎么回事&#xff0c;截图如下&#xff1a; 看了下是两个相同的程序&#xff0c;既然被打满了那就抓一个 dump 看看到底咋回事。 二&#xff1a;为什么会打…...

【Docker】Docker安装Kibana服务_Docker+Elasticsearch+Kibana

文章目录 1. 什么是Kibana2. Docker安装Kibana2.1. 前提2.2. 安装Kibana 点击跳转&#xff1a;Docker安装MySQL、Redis、RabbitMQ、Elasticsearch、Nacos等常见服务全套&#xff08;质量有保证&#xff0c;内容详情&#xff09; 1. 什么是Kibana Kibana 是一款适用于Elasticse…...

前端面试题-VUE

1. 对于MVVM的理解 MVVM 是 Model-View-ViewModel 的缩写Model 代表数据模型&#xff0c;也可以在 Model 中定义数据修改和操作的业务逻辑。View 代表 UI 组件&#xff0c;它负责将数据模型转化成 UI 展现出来。ViewModel 监听模型数据的改变和控制视图⾏为、处理⽤户交互&…...

Linux嵌入式平台安全启动理解介绍

一、意义 安全启动可以防止未授权的或是进行恶意篡改的软件在系统上运行,是系统安全的保护石,每一级的前一个镜像会对该镜像进行校验。 1.1 安全启动原理介绍 通过数字签名进行镜像完整性验证(使用到非对称加密算法和哈希算法) 签名过程: raw_image--->use ha…...

安全学习DAY09_加密逆向,特征识别

算法逆向&加密算法分类&#xff0c;特征识别 文章目录 算法逆向&加密算法分类&#xff0c;特征识别算法概念&#xff0c;分类单向散列加密 - MD5对称加密 - AES非对称加密 - RSA 常见加密算法识别特征&#xff0c;解密特点MD5密文特点BASE64编码特点AES、DES特点RSA密文…...

原型模式(Prototype)

原型模式是一种创建型设计模式&#xff0c;使调用方能够复制已有对象&#xff0c;而又无需使代码依赖它们所属的类。当有一个类的实例&#xff08;原型&#xff09;&#xff0c;并且想通过复制原型来创建新对象时&#xff0c;通常会使用原型模式。 The Prototype pattern is g…...

深度学习之用PyTorch实现线性回归

代码 # 调用库 import torch# 数据准备 x_data torch.Tensor([[1.0], [2.0], [3.0]]) # 训练集输入值 y_data torch.Tensor([[2.0], [4.0], [6.0]]) # 训练集输出值# 定义线性回归模型 class LinearModel(torch.nn.Module):def __init__(self):super(LinearModel, self)._…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例&#xff0c;模拟20个网页的爬取&#xff0c;每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程&#xff1a;允许程序同时执行多个任务&#xff0c;提高IO密集型任务&#xff08;如网络请求&#xff09;的效率…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...