2.1tarjian算法求解双连通分量

P2860 [USACO06JAN] Redundant Paths G

就是说通过加边,使得图中的每一点都不是割点,就是让连通图中没有桥,没有割点

并非是桥的数量-1

边双连通分量即一个无向图中,去掉一条边后仍互相连通的极大子图。(单独的一个点也可能是一个边双连通分量)

换言之,一个边双连通分量中不包含桥。

思路是

通过tarjan算法,这样所有弹出的点都归属于一个边-双联通分量。

将每个节点所归属的边-双连通分量后,我们可以将归属于一个边-双连通分量缩成新图上的一个节点,这样所形成的每个连通分量就是一棵树。然后我们需要证明一个定理:这个连通分量上的广义叶子节点(度数为1)除以2向上取整即为所需要加的边数

题目要求的是所有点至少度数为2,度数为1的点应该至少连一条边,最好的方法当然是一次性连两个度数为1的点,如果最后没有匹配(个数为奇数),仍然要连边,所以得出结论。

就是说,要求树里的点度数都至少为2,然后先是连边,连度数都为1的点,这样的话每条边都能消掉2个度为1的,这样的边共可以消掉x*2个度数为1的点,如果点的个数为偶数,那么恰好可以消完,但是如果是奇数,就会剩一个,此时就需要连边到度数不为1的上,此时这个边就只能消掉一个,而且仅存在这一条边,为奇数时;

不为奇数时,由于除法向下取整,所以也不会影响,所以就是Leaf+1/2

关键在于第二部缩点

首先我们要明白: 进行 e-DCC 缩点之后,最终形成的图是一棵树。

因为: 假设缩点之后的图不是树,那么一定存在一个环,因此这个环还可以缩成一个点,这产生了矛盾。

实际上等到我们把原图中所有的桥找出来以后,对不含桥的连通块缩点,会发现最后剩下的图是一个树。添加最少的边使这棵树上所有的链都变成环,则是本题的答案。这个答案可以由这棵树叶子节点数/2向上取整得出。(贪心,比较显然)

要通过Tarjan算法完成无向图的缩点,可以进行以下步骤:

1. 定义一些全局变量和数据结构。包括一个数组`dfn`和一个数组`low`,分别用于记录每个顶点的发现时间和低链接值;一个堆栈`sta`用于存储遍历过程中的顶点;一个整数`num`用于记录当前时间;一个整数`col`用于记录缩点后的新顶点的编号一个数组`color`用于记录每个顶点所属的缩点后的新顶点。

2. 定义一个函数`tarjan`,该函数接受一个顶点参数`u`。在函数内部,首先将当前顶点的发现时间和低链接值都初始化为当前时间`num`,然后将当前顶点入栈。

3. 遍历当前顶点的邻接边,对于每条边 `(u, v)`,进行以下操作:
   - 如果顶点`v`未被访问过(即`dfn[v]`等于0),则递归调用`tarjan`函数,并更新当前顶点的低链接值为当前顶点的低链接值和顶点`v`的低链接值中的较小值。
   - 如果顶点`v`已被访问过,并且它不是当前顶点的父节点,则更新当前顶点的低链接值为当前顶点的低链接值和顶点`v`的发现时间中的较小值。

4. 在当前顶点的低链接值等于发现时间的情况下,说明找到了一个连通分量。为了区分不同的连通分量,使用一个计数器`col`,将当前顶点和栈中的顶点都标记为同一个新顶点,即将`color`数组中对应的位置设置为`col`。

相等是找到一个强联通分量,如果dfn小于儿子,说明儿子有别的路回到更远;如果大于,说明儿子到不了父亲;就是说,每个连通分量里,有且仅有一个点满足相等的条件

在每个联通分量中,有且仅有一个点的低链接值等于发现时间。这个点通常称为“根”或“割点”。

这是因为在Tarjan算法中,对于一个联通分量而言,从任意一个顶点开始进行DFS遍历时,首个被访问到的顶点一定是“根”,也即发现时间最早的顶点。在这个根顶点的DFS子树中,通过向下逐层遍历,我们会发现在这个子树上其他的顶点的发现时间都不小于根顶点的发现时间。

由于Tarjan算法是通过DFS遍历来计算低链接值的,对于每个顶点,低链接值是根据它所能达到的最早发现时间的顶点进行更新的。因此,只有根顶点的低链接值等于发现时间,其他顶点的低链接值都大于根顶点的发现时间。

所以,在每个联通分量中,只有一个顶点的低链接值等于发现时间,其他顶点的低链接值都大于发现时间。这个顶点被称为割点,它是决定联通分量的关键点。

5. 在主函数中进行图的遍历。对于每个未被访问的顶点,调用`tarjan`函数来计算连通分量。

6. 最后,得到缩点后的图。新图的顶点数量为`col`,可以将原图中的每个顶点映射到新图中的对应顶点。根据缩点后的信息,可以进行后续的缩点操作,例如计算新图的入度、出度等。

通过以上步骤,就可以使用Tarjan算法完成无向图的缩点操作。这样可以将原始的图转换为一个更简化的图结构,方便进行后续的图算法处理。

这段代码是使用递归实现的深度优先搜索(DFS)算法,用于在有向图中找到强连通分量(SCC)。下面是代码的解释:

- 函数`dfs`以一个整数`cur`作为输入,表示当前正在访问DFS遍历中的节点。
- 变量`dfn`和`low`是数组,用于存储每个节点的DFS编号和低链接值。
- 变量`index_`用于跟踪每个节点的DFS编号。
- for循环遍历从当前节点`cur`出发的所有边。
- if条件检查边是否有效(即`tf[j]`为真)。如果是,则继续执行代码。
- 在if条件内部,代码检查目标节点`i`是否已被访问过(即`dfn[i]`为非零)。如果是,则使用`i`的DFS编号更新`cur`的低链接值。
- 如果目标节点`i`之前没有被访问过,代码将`i`推入一个栈`st`,标记当前边及其反向边为已访问即将`tf[j]`和`tf[(j&1)?j+1:j-1]`设置为假),并递归调用`dfs`函数来访问`i`。
- 递归调用结束后,代码通过将当前低链接值与`i`的低链接值的最小值来更新`cur`的低链接值。
- 如果`cur`的DFS编号和低链接值相等,则说明`cur`是一个新的SCC的根节点。
- 代码将`ans`变量加1,以计算SCC的数量。
- 然后,代码从栈`st`中弹出节点,并将它们分配给当前SCC,直到遇到`cur`节点。
- 最后,代码将SCC编号(`ans`)存储在弹出的节点中,即将其存储在`bcc`数组中。

注意:代码假设图的邻接表表示存储在数组`h`,`nxt`和`p`中。栈`st`用于存储当前SCC中的节点。`tf`数组用于跟踪哪些边已经被访问过。

这行代码是在标记强连通分量时的一部分操作。

代码的意思是,当栈顶的节点不等于当前节点`u`时将栈顶的节点(`sta[top]`)标记为属于当前的强连通分量(使用col来表示当前的强连通分量编号)然后将栈顶的指针`top`减1,即将栈顶节点出栈。

这行代码的作用是将栈中保存的一系列节点都标记为属于当前的强连通分量。由于Tarjan算法中,栈中的节点是按照DFS的顺序依次入栈的,而在找到一个强连通分量时,栈中的节点都是属于该强连通分量的。因此,这行代码将栈中的节点依次出栈,并将它们标记为当前的强连通分量。

请注意,这行代码前面的`top--`表示减小栈的指针,将栈顶指针移动到下一个位置,即将栈顶元素出栈,而在对栈顶元素进行标记后,`top--`是在执行标记后进行的。

就是说由于是递归dfs,所以先访问的最后才会出来,但是对栈的修改是在每层递归里都进行的,在栈中时,每个联通分量只会有一个是相等的关系,是这一组结点的根,在这个栈中结点之上的其他结点,它门的low都是比自己的dfn小的,而且等于它们的根结点

这段代码是一个寻找图中割点(Cut Point)数量的算法,并输出结果的实现代码。下面是代码的解释:

- `N`和`M`分别表示数组大小的常量,其中`N`为图中节点的最大数量,`M`为图中边的最大数量。
- `n`和`m`分别表示图中节点的数量和边的数量。
- `vis`是一个大小为`2*M`的数组,用于标记边是否已经被访问过。
- `du`是一个大小为`N`的数组,用于记录每个节点的度数。
- `ans`表示割点的数量。
- `cnt`表示边的计数器。
- `head`是一个大小为`N`的数组,用于存储每个节点的边链表的头节点。
- `u`和`v`是大小为`M`的数组,用于存储边的起点和终点。

函数解释:
- `add`函数用于向图中添加一条边。它接受两个参数`u`和`v`,表示边的起点和终点。在添加边的过程中,会更新边链表和度数数组。
- `tarjan`函数是Tarjan算法的实现,用于寻找强连通分量并标记割点。它接受一个参数`u`,表示当前正在访问的节点。在函数中,通过DFS遍历将图中的节点分为强连通分量,并标记割点。
- `main`函数是程序的主函数。在函数中,首先对数组进行初始化。
- 然后,通过输入获取图中的节点数量和边的数量,并利用`add`函数添加边。
- 接下来,使用`tarjan`函数找到强连通分量和割点,并标记割点的数量。
- 最后,输出割点的数量的一半。

`u`和`v`数组分别用于存储输入的每条边的起点和终点。在`main`函数中,通过`scanf`函数输入这些数据,然后通过`add`函数将这些边添加到图中。这样做是为了方便进行Tarjan算法的实现和处理割点的标记。

需要注意,这里缩点,vis数组记录的是对边的访问情况,

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/699587.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于编译器的静态代码分析与软件开发效率、质量和性能

基于编译器的静态代码分析与软件开发效率、质量和性能 本文节选自《基础软件之路:企业级实践及开源之路》一书,该书集结了中国几乎所有主流基础软件企业的实践案例,由 28 位知名专家共同编写,系统剖析了基础软件发展趋势、四大基…

袁庭新ES系列10节 | 使⽤kibana对⽂档操作

前言 在前面的小节中,我们已经给大家介绍了Elasticsearch中文档的相关概念,想必有些同学都已经忘记了,那我们一块儿再来回顾下,文档即索引库中某个类型下的数据,会根据规则创建索引,将来用来搜索。可以类比…

HTML+CSS:动态搜索框

效果演示 这段代码实现了一个简单的搜索栏效果。页面背景为从天蓝色到深蓝色的渐变色,搜索栏包括一个圆形背景的搜索图标和一个输入框。当用户点击搜索图标时,输入框会从搜索图标的位置滑出,显示一个输入框和一个清除按钮。用户可以在输入框中…

Unity(第三部)新手绘制地形

1、创建地形 游戏对象3d对象地形 2、功能 1、 红框内按键为创建相邻地形、点击后相近地形会呈现高亮框、点击高亮区域可以快速创建地形 每块地形面积是1km*1km 2、第二个按钮是修改地形 下面的选择是修改类型 选项含义描述Raise or Lower Terrain升高或降低地形单击左键可…

pikachu靶场-File Inclusion

介绍: File Inclusion(文件包含漏洞)概述 文件包含,是一个功能。在各种开发语言中都提供了内置的文件包含函数,其可以使开发人员在一个代码文件中直接包含(引入)另外一个代码文件。 比如 在PHP中,提供了&…

5G网络(接入网+承载网+核心网)

5G网络(接入网承载网核心网) 一、5G网络全网架构图 这张图分为左右两部分,右边为无线侧网络架构,左边为固定侧网络架构。 无线侧:手机或者集团客户通过基站接入到无线接入网,在接入网侧可以通过RTN或者IP…

如何在Linux Ubuntu系统使用Docker快速部署MongoDB并公网访问

文章目录 前言1. 安装Docker2. 使用Docker拉取MongoDB镜像3. 创建并启动MongoDB容器4. 本地连接测试5. 公网远程访问本地MongoDB容器5.1 内网穿透工具安装5.2 创建远程连接公网地址5.3 使用固定TCP地址远程访问 前言 本文主要介绍如何在Linux Ubuntu系统使用Docker快速部署Mon…

互联网加竞赛 机器视觉 opencv 深度学习 驾驶人脸疲劳检测系统 -python

文章目录 0 前言1 课题背景2 Dlib人脸识别2.1 简介2.2 Dlib优点2.3 相关代码2.4 人脸数据库2.5 人脸录入加识别效果 3 疲劳检测算法3.1 眼睛检测算法3.2 打哈欠检测算法3.3 点头检测算法 4 PyQt54.1 简介4.2相关界面代码 5 最后 0 前言 🔥 优质竞赛项目系列&#x…

8.qt5使用opencv的库函数打开图片

1.配置opencv动态库的环境变量 2.在创建的qt工程中加入如下opencv代码,具体代码如下: 使用opencv库函数显示图片

Linux进一步研究权限-----------ACL使用

一、使用情况 1.1、场景: 某个大公司,在一个部门,有一个经理和手下有两个员工,在操控一个Linux项目,项目又分为三期做,然而一期比较重要,经理带着员工做完了,公司就觉得技术难点已经做完攻克了&#xff0…

【自然语言处理-二-attention注意力 是什么】

自然语言处理二-attention 注意力机制 自然语言处理二-attention 注意力记忆能力回顾下RNN(也包括LSTM GRU)解决memory问题改进后基于attention注意力的modelmatch操作softmax操作softmax值与hidder layer的值做weight sum 计算和将计算出来的和作为memo…

《Python 语音转换简易速速上手小册》第1章 Python语音处理概述(2024 最新版)

文章目录 1.1 语音处理的基础1.1.1 基础知识1.1.2 主要案例:自动语音识别系统案例介绍案例 Demo案例分析1.1.3 扩展案例 1:智能虚拟助手案例介绍案例 Demo案例分析1.1.4 扩展案例 2:情感分析系统案例介绍案例 Demo

NATS学习笔记(一)

NATS是什么? NATS是一个开源的、轻量级、高性能的消息传递系统,它基于发布/订阅模式,由Apcera公司开发和维护。 NATS的功能 发布/订阅:NATS的核心是一个发布/订阅消息传递系统,允许消息生产者发布消息到特定的主题…

2024生物发酵魅力展示会-光德流体

参展企业介绍 河北光德流体控制有限公司始建于1996年,是一家从事以不锈钢为母材的洁净应用材料研发与专业制造的实体企业。产品主要包括卫生级球阀,隔膜阀,蝶阀等,并广泛应用于生物发酵,医疗制药,食品饮料…

初识51单片机

##江科大51单片机学习 什么是单片机??? 单片机,英文名,Micro Controller Unit,简称MCU(tips:有人会简称它为CPU,但不是如此,CPU其实被集成在MCU中&#xff…

视频评论抓取软件|抖音数据抓取工具

最近我们推出了一款基于C#语言开发的工具。这款工具提供了丰富的功能,旨在帮助用户轻松获取抖音视频内容。让我们一起来详细介绍一下这款工具的主要功能模块: 1. 批量视频提取: 工具提供了便捷的批量视频提取功能,用户只需输入关…

第3部分 原理篇2去中心化数字身份标识符(DID)(3)

3.2.2.4. DID文档 (DID Document) 本聪老师:DID标识符和DID URL还都只是ID,必须为它附加一个基本属性才可以证明是该主体独有的。这个就是我们下面介绍的DID文档。 本聪老师:每个DID标识符都唯一对应一个DID文档,也可以说&#x…

潇洒郎:2024 IDEA、Pycharm获取最新激活码获取方式

IDEA获取最新激活码 https://idea.javatiku.cn/ 手机打开,看到验证码,30分钟有效,输入验证码 获取到最新激活码

Redis(十六)缓存预热+缓存雪崩+缓存击穿+缓存穿透

文章目录 面试题缓存预热缓存雪崩解决方案 缓存穿透解决方案 缓存击穿解决方案案例:高并发聚划算业务 总结表格 面试题 缓存预热、雪崩、穿透、击穿分别是什么?你遇到过那几个情况?缓存预热你是怎么做的?如何避免或者减少缓存雪崩?穿透和击穿有什么区别?他两是…

基于大数据的智能家居销量数据分析

文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式 🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 &…