算法设计与分析(实验5)-----图论—桥问题

news2025/1/27 12:38:56

一.实验目的

  1. 掌握图的连通性。
  2. 掌握并查集的基本原理和应用。

二.实验步骤与结果

1.定义

(1)图的相关定义

图:由顶点的有穷非空集合和顶点之间的边的集合组成。

连通图:在无向图G中,若对于任意两点x与y有路径,则称x与y连通,图G为连通图。

连通分量:非连通图的极大连通子图为连通分量。

(2)桥的定义

在图论中,一条边被称为“桥”代表这条边一旦被删除,这张图的连通块数量会增加。等价地说,一条边是一座桥当且仅当这条边不在任何环上。一张图可以有零或多座桥。

2.解决问题

        找出一个无向图中所有的桥。

要求:

(1)实现基准算法。

(2)设计的高效算法中必须使用并查集,如有需要,可以配合使用其他任何数据结构。

(3)用图2的例子验证算法正确性。

(4)使用文件 mediumG.txt和largeG.txt 中的无向图测试基准算法和高效算法的性能,记录两个算法的运行时间。

(5)设计的高效算法的运行时间作为评分标准之一。

(6)提交程序源代码。

(7)实验报告中要详细描述算法设计的思想,核心步骤,使用的数据结构。

3.实验过程

(1)基准算法

①算法原理:

For every edge (u, v), do following

a) Remove (u, v) from graph

b) See if the graph remains connected (We can either use BFS or DFS)

c) Add (u, v) back to the graph.

 

②算法伪代码:

void jizhun(int edge_i)//遍历所有的边

      n1=count();

      remove(edge_i);//删掉该边

      n2=count();

      add(edge_i);//补回刚才暂时删掉的边

      if(n1!=n2)

           return 1;//该边是桥

      return 0;//该边不是桥

③时间复杂度分析:

穷举删除的边需要e次,每次删除都要dfs判断连通分支数目,需要O(n+e),复杂度O(e)

对于稀疏图(e=n):复杂度为(n^2)

对于稠密图(e=n^2):复杂度为(n^4)

 ④小规模测试:

不同规模下算法运行效率和理论值对比

表1 稀疏图下算法效率O(n^2)

1000

2000

3000

4000

5000

实验值

0.0636

0.2768

0.6843

1.1585

1.6531

理论值

0.0636

0.2544

0.5724

1.0176

1.59

表2 稠密图下算法效率O(n^4)

100

150

200

250

300

实验值

0.6469

3.0139

8.8914

22.2807

45.062

理论值

0.6469

3.274931

10.3504

25.26953

52.3989

        实验结果表明,基准算法解决桥问题理论值和实验值在不同数据规模下几乎相同,基准算法解决稀疏图理论分析得出的O(n^2)的平均时间复杂度是相对准确的,基准算法解决稠密图理论分析得出的O(n^4)的平均时间复杂度是相对准确的。 

(2)基准法+并查集

①算法原理:

        与基准法思路相同,通过删除边并计算连通分支数目来查找桥,计算连通分支时使用并查集。并查集计算连通分支数目的步骤为:枚举边,对每个边上的两点v1和v2,查询v1和v2所属的集合f1,f2,如果v1和v2不在同一个集合则合并v1和v2所属的两个集合,最后统计集合的个数,即为连通分支数目。

②算法伪代码:

void bingchaji()

      for u in agj[v]:

             f1=find(v)

             f2=find(u)

             if f1 != f2:

                   father[f2]=f1

int find(x)

       if father[x]==x

             return x;

       father[x]=find(father[x])  //路径压缩

return father[x];

使用路径压缩策略,使得并查集的查询复杂度均摊下来为O(1)

③时间复杂度分析:(其中 n为顶点数,e为边数)

穷举删除的边需要e次,每次删除都用并查集判断连通分支数目,需要O(e),复杂度O(e)

对于稀疏图(e=n),复杂度为O(n2),对于稠密图(e=n2),复杂度为O(n4)

稀疏图

1000

2000

3000

4000

5000

实际值

0.0668

0.3459

0.6208

1.1796

1.8812

理论值

0.0668

0.2672

0.6201

1.0688

1.67

稠密图

100

150

200

250

300

实际值

1.119

4.9772

15.8986

38.1267

80.5864

理论值

1.119

5.664938

17.904

43.71094

90.639

        实验结果表明,基准+并查集算法解决桥问题理论值和实验值在不同数据规模下几乎相同,基准+并查集算法解决稀疏图理论分析得出的O(n^2)的平均时间复杂度是相对准确的,基准算法解决稠密图理论分析得出的O(n^4)的平均时间复杂度是相对准确的。 

④优化效果

稀疏图

1000

2000

3000

4000

5000

优化前

0.0636

0.2768

0.6843

1.1585

1.6531

优化后

0.0668

0.3459

0.6208

1.1796

1.8812

        分析得知,当数据规模较小时,算法的优化效果不明显,接下来在基准+并查集的算法基础上再设计优化算法。

(3)基准+并查集+生成树

引入最近公共祖先LCA

在一棵没有环的树上,除根节点外每个节点都有其父节点和祖先节点,最近公共祖先就是两个节点在这棵树上深度最大的公共祖先节点。寻找两个节点的最近公共节点即根据两个节点的深度分别向树根方向查找,当查找到第一个相同节点时,该节点即为两个节点的最近公共祖先。

排除所有不是桥的边,剩下的即为桥。可以通过判断一条边是否在环上,进行桥的判断。树是边数最小的无环图,并且当向树上添加任意一条顶点都在树上的边,必定会形成环。而桥必定不在环上,一定存在于图的生成树上,所以除了图的生成树上的边,其他的边一定不是桥。基于这一想法,可以先构建生成树,再枚举不在生成树上的所有边,并根据最近公共祖(LCA)排除加入这些边后生成的环所在的边,最后剩下的边即为桥。

 ②生成树:

因为桥边一定会出现在生成树上,所以对于基准法,我们只需要枚举生成树上的边,而不需要枚举所有的边,就能找到答案。生成树优化能够使得枚举边的代价从O(e)变为O(n)。

生成树的构建:使用 DFS 遍历,并在DFS 遍历时根据得到的生成树中边前驱与后继的关系为并查集设置好各个节点的父节点。

环的搜索与桥的标记:引入最近公共祖先来保证向上寻找祖先时每条边只被经过一次。将这些在环中的边标记为非桥。对边的标记可以通过对点数组的操作来实现节省空间。

路径压缩:对于层数较深的节点,需要多次递归才能找到最近公共祖先(LCA),并且,在递归过程中一直沿着完全一样的递归路径进行递归,造成了很多无用的向上递归。运用并查集对路径进行压缩,可以降低层数较深节点的最近公共祖先(LCA)递归时间。

③时间复杂度分析

(顶点个数为n,边个数为)

DFS构建生成树时间复杂度为O(n+e);为并查集设置父节点时间复杂度为O(n);一次查找最近公共祖先最差情况下要查找n次,时间复杂度O(n) ;一次路径压缩最差情况时间复杂度也为O(n);总共需要执行e-m次查找(m为生成树边数),因此算法的总时间复杂为:

 T=O(n+e)+O(n)+(e−m)×O(n)=O(en)

        查找的时间复杂度O(n)是最差情况,对于大数据量级下的查找操作,经过并查集的路径压缩,很快需要查找的节点基本上父节点大部分都已经被设置为最近公共祖先(LCA)。此时,查找的时间会接近O(1)。此时有:

即对大数据下算法的时间效率得到了极大提升。

伪代码

LCA(u, v)

if (father[u] == v || father[v] == u)

return

u1 = u, v1 = v;

while(true)

if depth[u]>depth[v]

tag[v]=0,v=father[v]

else

if u!=v

tag[u]=0,tag[v]=0

    u=father[u]

v=father[v]

else break

unzip(u1,u),unzip(v1,v)

Unzip(x, v)

if father[x] == v

return

else

tempx = x

x = father[x];

    father[temp] = v;

Upzip(x, v)

 ⑤时间效率分析

(5)大规模测试

        由于largeG数据集过大,在二维数组过大时使用DFS/BFS递归时可能会出现栈空间不足而无法处理数据从而得到可行解,故先对于IDE进行栈空间的扩充。

        采用优化算法对大规模测试数据进行求解:

 (6)其他优化算法

Tarjan算法是一个基于深度优先搜索(DFS)的图算法,用于寻找一个有向图中的强连通分量。

伪代码:

void Tarjan(G(E,V))

function Tarjan-SCC(v):

  v.index = index

  v.lowlink = index

  index = index + 1

  stack.push(v)

  

  for each edge (v, w) in E:

    if w.index is undefined:

      Tarjan-SCC(w)

      v.lowlink = min(v.lowlink, w.lowlink)

    else if w is in stack:

      v.lowlink = min(v.lowlink, w.index)

  

  if v.lowlink = v.index:

    SCC = []

    repeat

      w = stack.pop()

      SCC.add(w)

    until w = v

    SCCs.add(SCC)

for each vertex v in V:

  if v.index is undefined:

    Tarjan-SCC(v)

算法效率:

基准算法

基准+并查集+生成树

Tarjan

largeG测试运行时间

无解

2.987s

1.692s

通过测试得知,算法效率大大提升。

        除此之外,还可以加入编译优化:由于算法过程中使用了大量的STL容器,因此在编译时应该选择进行O3优化,大致可以将程序的运行时间缩短至原来的一半。

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

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

相关文章

nestjs 全栈进阶--module

视频教程 10_模块Module1_哔哩哔哩_bilibili 1. 模块Module 在 Nest.js 中,Module 是框架的核心概念之一,用于组织和管理应用程序的不同部分,包括服务、控制器、中间件以及其他模块的导入。每个 Nest.js 应用程序至少有一个根模块&#xf…

log4j 集成 ELK环境搭建

一、前言 1.需要准备一台linux服务器(最好是CentOS7),内存至少4g以上(三个组件都比较占用内存) 2.需要有docker使用经验 3. 三个软件的版本要一致 二、安装ElasticSearch 这里先创建一个网络:因为我们还需要部署k…

J基于微信小程序的电影订票、电影购票小程序

文章目录 1 **摘 要**2 技术简介**3 系统功能设计****第4章 系统设计****4.1系统结构设计** 第5章 系统实现**5.1管理员服务端功能模块**5.2用户客户端功能模块 结 论6 推荐阅读7 源码获取: 1 摘 要 本文从管理员、用户的功能要求出发,电影订票系统小程…

Python---Numpy线性代数

1.数组和矩阵操作: 创建数组和矩阵:np.array, np.matrix 基本的数组操作:形状修改、大小调整、转置等 import numpy as np# 创建一个 2x3 的数组 A np.array([[1, 2, 3], [4, 5, 6]]) print("数组 A:\n", A)# 将数组 A 转换为矩阵…

探究“大模型+机器人”的现状和未来

基础模型(Foundation Models)是近年来人工智能领域的重要突破,在自然语言处理和计算机视觉等领域取得了显著成果。将基础模型引入机器人学,有望从感知、决策和控制等方面提升机器人系统的性能,推动机器人学的发展。由斯坦福大学、普林斯顿大学…

javaer 为什么称redis、rabbitmq这些东西为中间件?

中间件(Middleware)是位于客户端和服务器端之间的软件服务层,它提供了一种通用服务的方式,帮助不同的应用程序、系统组件和服务之间进行交互和数据交换。中间件隐藏了底层的复杂性,使得开发者可以专注于业务逻辑的实现…

基于JSP SSM的社区生活超市管理系统

目录 背景 技术简介 系统简介 界面预览 背景 随着时代步伐的加速,计算机技术已广泛而深刻地渗透到社会的各个层面。随着居民生活水平的持续提升,人们对社区生活超市的期望和管理要求也越来越高。随着社区生活超市数量的稳步增长,开发一个…

Coding and Paper Letter(八十八)

系列重启之CPL。 1 Coding: 1.一个Python库用来分析城市路网的工具箱,城市形态分析工具。 Madina 2.SkyPilot:在任何云上运行 LLM、AI 和 Batch。 通过简单的界面即可实现最大程度的节省性能、最高的 GPU 可用性和托管执行。 skypilot 3.探索美国卫…

Apache-Pulsar安装操作说明

说明 Pulsar 是一种用于服务器到服务器消息传递的多租户高性能解决方案。 Pulsar 的主要特性如下: 对 Pulsar 实例中的多个集群的本机支持,并跨集群无缝地复制消息。 极低的发布和端到端延迟。 无缝可扩展至超过一百万个主题。 一个简单的客户端 API&…

arcgis10.5安装步骤

目录 一、安装License 二、安装ArcGIS_Desktop 三、安装汉化包,解压后,直接双击等待安装即可 一、安装License 双击ArcGIS_License_Manager_Windows_105_154033 选择【Next】 勾选I accept,然后选择【Next】 选择License的安装目录&#x…

实战webSocket压测(三)Jmeter真实接口联调

背景: 接口地址为:ws://sunlei.demo 接口说明:websocket接口,首次连接,通过Text请求设置开启标志,然后通过wav文件流传输,达到后端服务可以根据传输信息进行解析满足指定标准后,web…

SpringBoot响应式RedisClient配置

大多数场景,默认配置的Redis客户端不满足业务场景,根源在于Redis key、value 序列化反序列化问题。因此,有必要配置自定义的客户端来满足需求。 默认配置源码如下,采用jdk序列化/反序列化方式进行,我们只需要配置相同…

SpringMVC数据响应和请求

文章目录 1.SpringMVC简介2. SpringMVC快速入门3. SpringMVC执行的流程4.SpringMVC注解解释5. 视图解析器6.SpringMVC的数据响应6.1返回ModelView对象6.2直接返回字符串6.3返回json字符串 7.SpringMVC获得请求数据7.1 获得基本类型参数7.2获得POJO类型参数7.3获取数组类型参数7…

基于Swin Transformers的乳腺癌组织病理学图像多分类

乳腺癌的非侵入性诊断程序涉及体检和成像技术,如乳房X光检查、超声检查和磁共振成像。成像程序对于更全面地评估癌症区域和识别癌症亚型的敏感性较低。 CNN表现出固有的归纳偏差,并且对于图像中感兴趣对象的平移、旋转和位置有所不同。因此,…

WPS解决插入公式在正文带来行间距变大问题

问题描述 写论文解释公式时,插入对应的变量,导致行间距变大,如图 显然上文与下文行间距不等。但无法通过修改数值修改下文行间距。 解决办法

(已解决)引入本地bootstrap无效,bootstrap和jquery的引入

问题&#xff1a; 首先我是跟着张天宇老师下载的bootstrap文件&#xff0c;新建了一个css文件夹&#xff0c;但是这样子<link rel"stylesheet" type"text/css" src"./css/bootstrap.css">在index.html引入没有用。 解决办法: 1.把建立的…

贪心算法|1005.K次取反后最大化的数组和

力扣题目链接 class Solution { static bool cmp(int a, int b) {return abs(a) > abs(b); } public:int largestSumAfterKNegations(vector<int>& A, int K) {sort(A.begin(), A.end(), cmp); // 第一步for (int i 0; i < A.size(); i) { // 第二步if…

DSOX3034T是德科技DSOX3034T示波器

181/2461/8938产品概述&#xff1a; 特点: 带宽:350 MHz频道:4存储深度:4 Mpts采样速率:5 GSa/s更新速率:每秒1000000个波形波形数学和FFT自动探测接口用于连接、存储设备和打印的USB主机和设备端口 触摸: 8.5英寸电容式触摸屏专为触摸界面设计 发现: 业界最快的无损波形更…

MSOLSpray:一款针对微软在线账号(AzureO365)的密码喷射与安全测试工具

关于MSOLSpray MSOLSpray是一款针对微软在线账号&#xff08;Azure/O365&#xff09;的密码喷射与安全测试工具&#xff0c;在该工具的帮助下&#xff0c;广大研究人员可以直接对目标账户执行安全检测。支持检测的内容包括目标账号凭证是否有效、账号是否启用了MFA、租户账号是…

[开源]基于SVM的时间序列预测python代码

整理了SVM的时间序列预测python代码分享给大家。记得点赞哦 #!/usr/bin/env python # coding: utf-8import numpy as np import matplotlib.pyplot as plt import pandas as pd from sklearn import preprocessing from sklearn.metrics import mean_squared_error from math i…