C++算法:图中的最短环

news2024/12/24 17:13:30

题目

现有一个含 n 个顶点的 双向 图,每个顶点按从 0 到 n - 1 标记。图中的边由二维整数数组 edges 表示,其中 edges[i] = [ui, vi] 表示顶点 ui 和 vi 之间存在一条边。每对顶点最多通过一条边连接,并且不存在与自身相连的顶点。
返回图中 最短 环的长度。如果不存在环,则返回 -1 。
环 是指以同一节点开始和结束,并且路径中的每条边仅使用一次。
2 <= n <= 1000
1 <= edges.length <= 1000
edges[i].length == 2
0 <= ui, vi < n
ui != vi
不存在重复的边

分析

在这里插入图片描述

返回还是真环

利用BFS求到A的最短距离,B和C到A的距离都为1,处理BC是发现B和C都已经和A连通,说明存在环。注意:求EFG到点D的距离,处理完DE ED EF FE FG后,处理GF,发现F和G都和D连通。判断是返回,还是真环有两种思路:
一,记录已经使用的双向边,枚举新边的时候,忽略。此方案容易理解。
二,记录各点的最短距离的前一点。此方案性能。

各点都要BFS

如果以H为源点,则最短的环长4。以k为源点,最短的环是3。

多个连通区域

由于所有点都会作为起点,所以所有点都会处理。和起点不连通的点不会重复处理。

不会遗漏任意环

某个包括x的奇数长度的环,假定其长度为len2+1,环上有两个点距离x为len,假定先处理的为x1,后处理的为x2。处理x1->x2是发现此环。假定此环长为偶数,假定其长度为len2+2。环上有两个点距离x为len,假定先处理的为x1,后处理的为x2。距离x为len+1的点为x3,则处理x2->x3时,发现此环

不会误判环

发现cur和next都和源点连通,那说明next在cur之前已经处理,也就是vDis[next] <= vDis[cur]。vDis[next]不会比v[cur]小2,否则源点->next->cur更短。也就是vDis[next]和vDis[cur]相等或少1。源点到next的最短路径,不会包括cur,否则vDis[next]大于v[cur]。两者相等的情况,cur的最短路径不会包括next。少1的情况,如果cur的最短路径包括next,则最后一条边是next->cur。

方案一代码

class Solution {
public:
int findShortestCycle(int n, vector<vector>& edges) {
CNeiBo2 neiBo(n, edges, false);
for (int i = 0; i < n; i++)
{
Do(neiBo.m_vNeiB, i);
}
return (INT_MAX == m_iMinCycle) ? -1 : m_iMinCycle;
}
void Do(const vector<vector>& vNeiB, int src)
{
int n = vNeiB.size();
vector<unordered_set> setHas(n);
vector vDis(n, -1);
queue q;
vDis[src] = 0;
q.emplace(src);
while (q.size())
{
const auto cur = q.front();
q.pop();
for (const auto& next : vNeiB[cur])
{
if (setHas[next].count(cur))
{
continue;
}
setHas[cur].emplace(next);
if (-1 != vDis[next])
{
m_iMinCycle = min(m_iMinCycle, vDis[cur] + vDis[next] + 1);
continue;
}
vDis[next] = vDis[cur] + 1;
q.emplace(next);
}
}
}
int m_iMinCycle = INT_MAX;
};

方案二代码

class Solution {
public:
  int findShortestCycle(int n, vector<vector<int>>& edges) {
    CNeiBo2 neiBo(n, edges, false);
    for (int i = 0; i < n; i++)
    {
      Do(neiBo.m_vNeiB, i);
    }
    return (INT_MAX == m_iMinCycle) ? -1 : m_iMinCycle;
  }
  void Do(const vector<vector<int>>& vNeiB, int src)
  {
    int n = vNeiB.size();
    vector<int> vDis(n, -1), vPre(n,-1);
    queue<int> q;
    vDis[src] = 0;
    vPre[src] = -1;
    q.emplace(src);
    while (q.size())
    {
      const auto cur = q.front();
      q.pop();
      for (const auto& next : vNeiB[cur])
      {   
        if (-1 != vDis[next])
        {
          if (vPre[cur] != next)
          {
            m_iMinCycle = min(m_iMinCycle, vDis[cur] + vDis[next] + 1);
          }
          continue;
        }
        vDis[next] = vDis[cur] + 1;
        vPre[next] = cur;
        q.emplace(next);
      }
    }   
  }
  int m_iMinCycle = INT_MAX;
};

方案三

方案一和方案二时间复杂度都是O(n^2),方案一比方案二慢。方案三相比方案一,稍稍提速。
void Do(const vector<vector>& vNeiB, int src)
{
int n = vNeiB.size();

vector<int> vDis(n, -1);
queue<int> q;
vDis[src] = 0;
q.emplace(src);
while (q.size())
{
  const auto cur = q.front();
  q.pop();
  for (const auto& next : vNeiB[cur])
  {
    if (m_vHasDo[next][cur])
    {
      continue;
    }
    m_vHasDo[cur][next] = 1;
    if (-1 != vDis[next])
    {
      m_iMinCycle = min(m_iMinCycle, vDis[cur] + vDis[next] + 1);
      continue;
    }
    vDis[next] = vDis[cur] + 1;
    q.emplace(next);
  }
}

}

2023年4月版本

class Solution {
public:
int findShortestCycle(int n, vector<vector>& edges) {
m_iN = n;
m_vNeiB.resize(n);
for (const auto&v : edges)
{
m_vNeiB[v[0]].emplace_back(v[1]);
m_vNeiB[v[1]].emplace_back(v[0]);
}

	for (int i = 0; i < n; i++)
	{
		bfs(i);
	}
	return (INT_MAX == m_iRet) ? -1 : m_iRet;
}
void bfs(int iRoot)
{
	std::vector<int> vDis(m_iN, -1);
	vDis[iRoot] = 0;
	std::queue<pair<int,int>> que;
	que.emplace(iRoot, -1);//当前节点,父节点
	while (que.size())
	{
		const int iPre = que.front().first;
		const int iPrePre = que.front().second;
		que.pop();
		for (const auto& next : m_vNeiB[iPre])
		{
			if (-1 == vDis[next])
			{
				vDis[next] = vDis[iPre] + 1;
				que.emplace(next, iPre);
			}
			else
			{
				if (next == iPrePre)
				{
					continue;
				}
				m_iRet = min(m_iRet, vDis[iPre] + 1 + vDis[next]);
			}
		}
		
	}
}
vector<std::vector<int>> m_vNeiB;

int m_iN;
int m_iRet = INT_MAX;

};

其它

视频课程

如果你觉得复杂,想从简单的算法开始,可以学习我的视频课程。
https://edu.csdn.net/course/detail/38771
我的其它课程
https://edu.csdn.net/lecturer/6176

测试环境

win7 VS2019 C++17

相关下载

算法精讲《闻缺陷则喜算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

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

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

相关文章

【Python中单引号、双引号和三引号具体的用法及注意点】

Python中单引号、双引号和三引号具体的用法及注意点 这篇文章主要给大家介绍了关于Python中单引号、双引号和三引号具体的用法及注意点的相关资料,Python中单引号、双引号、三引号中使用常常困惑,想弄明白这三者相同点和不同点,需要的朋友可以参考下 文章目录 Python中单引号、…

Zabbix监控系统详解1 :zabbix服务部署、自定义监控项、自动发现与自动注册

文章目录 1. Zabbix 概述1.1 简介1.2 zabbix的功能组件1.2.1 Zabbix Server1.2.2 数据库1.2.3 Web 界面1.2.4 Zabbix Agent1.2.5 Zabbix Proxy1.2.6 Java Gateway 1.3 工作原理1.4 常用端口号1.5 zabbix中预设的键值1.6 自定义监控项相关流程1.7 邮件报警配置思路1.8 Zabbix自动…

气膜建筑的可持续性:能源效益与环境影响

气膜建筑作为现代建筑技术的一种创新形式&#xff0c;不仅为城市景观增添了未来感&#xff0c;同时也在建筑领域引发了可持续性发展的讨论。本文将探讨气膜建筑在可持续性方面的关键议题&#xff0c;特别聚焦于其能源效益和环境影响&#xff0c;以期为未来气膜建筑设计和规划提…

dm关键字提示报错

问题出现 还是那个项目&#xff0c;然后呢因为其中涉及到了关键字&#xff0c;导致查询报错&#xff0c; 提示是REFERENCE出现错误。 问题处理 对于所有的关键字增加双引号可以处理。

服务器中了balckhoues勒索病毒怎么办?勒索病毒解密,数据恢复

近日&#xff0c;云天数据恢复中心发现&#xff0c;有多位用户的服务器中了一种名为balckhoues的勒索病毒&#xff0c;因为绝大多数用户是第一次遇到这种情况&#xff0c;所以对这种类型的勒索病毒并不是很了解。那接下来我们将对balckhoues勒索病毒做一个分析。 中毒特征 服务…

10.12作业

以下是一个简单的比喻&#xff0c;将多态概念与生活中的实际情况相联系&#xff1a; 比喻&#xff1a;动物园的讲解员和动物表演 想象一下你去了一家动物园&#xff0c;看到了许多不同种类的动物&#xff0c;如狮子、大象、猴子等。现在&#xff0c;动物园里有一位讲解员&…

运放供电设计 以及电压反馈电流反馈选择

因为OPA350可以直接驱动大电容 不需要对称&#xff0c;只要输出在电压范围内就可以 注&#xff1a;电流反馈运放一定要注意电阻取值&#xff0c;并且不能并电容

如何swagger关闭及给swagger加参数信息

项目的swagger方便研发人员调试&#xff0c;上线之后需要将swagger关闭这时候需要给原来的Configuration注解换成ConditionlOnProperty注解及可。注解参数信息 ConditionalOnProperty(name "swagger.enable", havingValue "true")若swagger想加入额外参…

Halcon我的基础教程(一)(我的菜鸟教程笔记)-halcon仿射变换(Affine Transformation)的探究与学习

目录 什么是仿射变换?仿射变换有哪些方式?任何仿射变换都能由以下基本变换构造而来:在Halocn中,仿射变换具有重要的作用,那我们本文章重点讨论仿射变换基础性知识。 使用Halcon中的重要算子,仿射变换一般解决步骤,案例应用会在以后的文章中我们重点解答与讨论。 我们首先…

基于 ceph-deploy 部署 Ceph 集群 超详细

Ceph part1 一、存储基础1.1 单机存储设备1.2 单机存储的问题1.3 单机存储问题的解决方案1.3.1 商业存储解决方案1.3.2 分布式存储&#xff08;软件定义的存储 SDS&#xff09; 二、分布式存储2.1 常见的分布式存储2.2 分布式存储的类型 三、Ceph概述3.1 Ceph简介3.2 Ceph 优势…

【另类加法】

目录 一、题目解析二、算法原理三、代码实现 一、题目解析 二、算法原理 三、代码实现 class Solution {public:int add(int A, int B){if(A 0)return B;else if(B 0)return A;elsereturn add(A^B, (A&B)<<1);} }

ASEMI整流桥KBU810参数,KBU810特性

编辑-Z KBU810参数描述&#xff1a; 型号&#xff1a;KBU810 最大直流反向电压VR&#xff1a;1000V 最大工作峰值反向电压VRWM&#xff1a;700V 最大平均正向电流IF&#xff1a;8A 非重复正向浪涌电流IFSM&#xff1a;300A 操作和储存温度范围TJ ,TSTG&#xff1a;-55 t…

LeetCode【1】两数之和

题目&#xff1a; 代码&#xff1a; public int[] twoSum(int[] nums, int target) {int[] result new int[2];Map<Integer, Integer> map new HashMap<>();// for (int i 0; i < nums.length; i) { // 这么写不能防重复啊&#xff01;注意这里不…

低功耗Sub-1G全频段收发一体芯片DP4306 适用无线对讲机 工业数据采集等应用

无线电对讲机既是移动通信中的一种专业无线通信工具&#xff0c;又是一种能满足人们生活需要的具有消费类产品特点的消费工具。顾名思义移动通信就是通信一方和另一方在移动中实现通信。 它是一种无线的可在移动中使用的一点对多点进行通信的终端设备&#xff0c;可使许多人同时…

【工具软件】在 window11 下使用微信读书app

作者&#xff1a;你们是大牛 链接&#xff1a;https://www.zhihu.com/question/340264583/answer/2439158730 来源&#xff1a;知乎 著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。 在windows11上可以使用wsa, 也就是windows下的安卓子系统…

完美解决 :ModuleNotFoundError: No module named ‘dlib‘

目录 1&#xff0c;报错信息 解决办法&#xff1a; 1&#xff0c;报错信息 尝试 pip install dlib 报错&#xff1a; 尝试解决办法&#xff1a; Python3.6版本——下载文件&#xff1a; dlib-19.6.0-cp36-cp36m-win_amd64.whl 下载网址 :dlib PyPI Python3.7版本——下载…

react中利用useRef、forwardRef、useImperativeHandle获取并处理dom

React如何给组件设置ref属性&#xff0c;如果直接绑给组件&#xff0c;代码如下&#xff1a; import { useRef } from "react"function MyInput() {return (<input type"text"/>) }function App() {const myRef useRef(null)const handleClick ()…

第一次汇报相关问题

深度学习现在已经学习到了Mini-Batch&#xff0c;early-stop等针对特定场景优化的算法了。 代码已经实现了一个L层的神经网络的构建了 论文看了一些综述 主要思考的两个方向&#xff1a;云计算和嵌入式 云计算&#xff1a;分布式机器学习、联邦学习、服务器负载均衡等 嵌入式&…

安卓wakelock机制

安卓wakelock机制 1.Wakelock作用2.WakeLock锁分类3.WakeLock的级别level 1.Wakelock作用 当手机灭屏状态下保持一段时间后&#xff0c;系统会进入休眠&#xff0c;这时&#xff0c;Android系统中CPU会保持在一个相对较低的功耗状态&#xff0c;一些后台运行的任务就可能得不到…

扁圆头带榫螺栓

声明 本文是学习GB-T 15-2013 扁圆头带榫螺栓. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了螺纹规格为M6&#xff5e;M24、 产品等级为C 级的扁圆头带榫螺栓。 2 规范性引用文件 下列文件对于本文件的应用是必不可少的。凡是…