【图论】判断图中有环的两种方法及实现

判断图中有环的两种方法及实现

在图论中,检测有向图是否存在环是常见问题。本文将介绍两种主流方法:DFS三色标记法拓扑排序(Kahn算法),并提供对应的C++代码实现。


方法一:DFS三色标记法

核心思想

通过深度优先搜索(DFS)遍历图,使用三种颜色标记节点状态:

  • 0(未访问):节点尚未被访问。
  • 1(访问中):节点正在被访问,其后续节点仍在递归中。
  • 2(已访问):节点及其所有后代均已处理完毕。

如果在遍历过程中遇到状态为1的节点,说明存在环

时间复杂度

  • O(V + E),其中V为节点数,E为边数。

C++代码实现

#include <vector>
using namespace std;bool hasCycleDFS(vector<vector<int>>& graph, int node, vector<int>& color) {color[node] = 1; // 标记为“访问中”for (int neighbor : graph[node]) {if (color[neighbor] == 0) { // 未访问的节点if (hasCycleDFS(graph, neighbor, color)) return true;} else if (color[neighbor] == 1) { // 遇到访问中的节点,存在环return true;}}color[node] = 2; // 标记为“已访问”return false;
}bool hasCycle(vector<vector<int>>& graph) {int n = graph.size();vector<int> color(n, 0); // 初始化所有节点为未访问for (int i = 0; i < n; ++i) {if (color[i] == 0 && hasCycleDFS(graph, i, color)) {return true;}}return false;
}

方法二:拓扑排序(Kahn算法)

核心思想

  1. 统计每个节点的入度(指向该节点的边数)。
  2. 将所有入度为0的节点加入队列。
  3. 依次处理队列中的节点,减少其邻居的入度。若邻居入度变为0,则加入队列。
  4. 若最终处理的节点数不等于总节点数,则存在环。

时间复杂度

  • O(V + E),其中V为节点数,E为边数。

C++代码实现

#include <vector>
#include <queue>
using namespace std;bool hasCycleTopo(vector<vector<int>>& graph) {int n = graph.size();vector<int> indegree(n, 0);queue<int> q;// 计算初始入度for (int u = 0; u < n; ++u) {for (int v : graph[u]) {indegree[v]++;}}// 入度为0的节点入队for (int i = 0; i < n; ++i) {if (indegree[i] == 0) q.push(i);}int cnt = 0; // 记录处理的节点数while (!q.empty()) {int u = q.front();q.pop();cnt++;for (int v : graph[u]) {if (--indegree[v] == 0) {q.push(v);}}}return cnt != n; // 存在环时cnt < n
}

方法对比与适用场景

方法优势劣势适用场景
DFS三色标记法可同时处理其他任务(如路径记录)递归深度可能较大需要深度遍历信息的场景
拓扑排序无需递归,适合大规模图仅提供是否存在环的结果只需判断环或需要拓扑序列的场景

完整测试代码

#include <iostream>
#include <vector>
#include <queue>
using namespace std;// DFS三色标记法
bool hasCycleDFS(vector<vector<int>>& graph, int node, vector<int>& color) {color[node] = 1;for (int v : graph[node]) {if (color[v] == 0) {if (hasCycleDFS(graph, v, color)) return true;} else if (color[v] == 1) {return true;}}color[node] = 2;return false;
}bool hasCycleDFS(vector<vector<int>>& graph) {int n = graph.size();vector<int> color(n, 0);for (int i = 0; i < n; ++i) {if (color[i] == 0 && hasCycleDFS(graph, i, color)) {return true;}}return false;
}// 拓扑排序
bool hasCycleTopo(vector<vector<int>>& graph) {int n = graph.size();vector<int> indegree(n, 0);queue<int> q;for (auto& edges : graph) {for (int v : edges) indegree[v]++;}for (int i = 0; i < n; ++i) {if (indegree[i] == 0) q.push(i);}int cnt = 0;while (!q.empty()) {int u = q.front();q.pop();cnt++;for (int v : graph[u]) {if (--indegree[v] == 0) q.push(v);}}return cnt != n;
}int main() {// 示例:有环图 0->1->2->0vector<vector<int>> graph = {{1}, {2}, {0}};cout << "DFS三色标记法结果: " << (hasCycleDFS(graph) ? "有环" : "无环") << endl;cout << "拓扑排序结果: " << (hasCycleTopo(graph) ? "有环" : "无环") << endl;return 0;
}

通过这两种方法,可以高效判断有向图中是否存在环。实际应用中,若需要拓扑序列则优先选择Kahn算法,若需深度遍历信息则选择DFS三色标记法。

(本文由deepseek总结生成)

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

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

相关文章

11.【线性代数】——矩阵空间,秩1矩阵,小世界图

十一 矩阵空间&#xff0c;秩1矩阵&#xff0c;小世界图 1. 矩阵空间交集 和 和集 2. 所有解空间3. r 1 r1 r1的矩阵4. 题目5. 小世界图 空间&#xff1a;组成空间的元素的线性组合都在这个空间中。 1. 矩阵空间 举例&#xff1a;矩阵空间&#xff08; M M M 所有3x3的矩阵&…

【网络安全 | 渗透测试】GraphQL精讲一:基础知识

未经许可,不得转载, 文章目录 GraphQL 定义GraphQL 工作原理GraphQL 模式GraphQL 查询GraphQL 变更(Mutations)查询(Queries)和变更(Mutations)的组成部分字段(Fields)参数(Arguments)变量别名(Aliases)片段(Fragments)订阅(Subscriptions)自省(Introspecti…

关于虚拟环境中遇到的bug

conda和cmd介绍 介绍 Conda 概述&#xff1a; Conda是一个开源包管理系统和环境管理系统&#xff0c;尤其适用于Python和R语言的开发环境。它允许用户创建独立的虚拟环境&#xff0c;方便地管理依赖包和软件版本。 特点&#xff1a; 环境管理&#xff1a;可以创建、导入、导…

基于nginx的灰度发布解决方案

Nginx 在灰度发布中可以看作是一个精确的流量调度员&#xff0c;它充当着客户端与后端服务器之间的中介。通过配置好的规则&#xff0c;Nginx 会将用户请求智能地引导到不同版本的服务上。这样&#xff0c;Nginx 可以根据具体需求灵活地分配流量&#xff0c;确保新版本逐步推向…

网络安全法与等级保护 PPT 精华汇总

资源描述 本资源文件为《网络安全法与等级保护》的PPT精华汇总&#xff0c;内容涵盖了网络安全法与等级保护的总体框架及相关标准规范。该PPT详细介绍了网络安全法与等级保护的各个章节和条款&#xff0c;并提供了基础类和应用类的相关标准文件&#xff0c;帮助读者全面了解和…

uni-app开发安卓和iOS 打包流程(云打包)

首先讲一下安卓打包的流程,之后再说ios。打包安卓和iOS打包的流程有些不同,安卓打包相对来说比较简单,而iOS打包需要更多的准备工作,如申请开发者账号、生成证书等。 一、安卓打包 1、安卓打包直接在window电脑上就可以操作,打开hbuilderx,找到你的项目选中,然后点击发…

摄像头应用编程(四):ARM Linux LCD实时预览UVC摄像头画面

文章目录 1、前言2、环境介绍3、步骤4、应用程序编写4.1、lcd初始化4.2、摄像头初始化4.3、jpeg解码4.4、开启摄像头4.5、完整的程序如下 5、测试5.1、编译应用程序5.2、运行应用程序 6、总结 1、前言 本次应用程序主要针对支持MJPEG格式输出的UVC摄像头。 2、环境介绍 rk35…

蓝桥与力扣刷题(蓝桥 k倍区间)

题目&#xff1a;给定一个长度为 N 的数列&#xff0c;A1,A2,⋯AN​&#xff0c;如果其中一段连续的子序列 Ai,Ai1,⋯Aj( i≤j ) 之和是 K 的倍数&#xff0c;我们就称这个区间[i,j] 是 K 倍区间。 你能求出数列中总共有多少个 K 倍区间吗&#xff1f; 输入描述 第一行包含两…

json介绍、python数据和json数据的相互转换

目录 一 json介绍 json是什么&#xff1f; 用处 Json 和 XML 对比 各语言对Json的支持情况 Json规范详解 二 python数据和json数据的相互转换 dumps() : 转换成json loads(): 转换成python数据 总结 一 json介绍 json是什么&#xff1f; 实质上是一条字符串 是一种…

PAT乙级真题 / 知识点(1)

引言&#xff1a; 起初&#xff0c;报PAT是伙伴推荐。但在报名路途中&#xff0c;有朋友说&#xff0c;花时间到这上面不值得&#xff0c;还有学长说没听过&#xff0c;野鸡杯。 我一笑而过&#xff0c;我可能就是偏执&#xff0c;我就是想报。随着刷真题&#xff0c;我的基础…

单细胞分析(20)——inferCNV分析

InferCNV分析笔记 1. 分析目标 InferCNV&#xff08;Inference of Copy Number Variations&#xff09;是一种基于单细胞转录组数据推断**拷贝数变异&#xff08;CNV&#xff09;**的方法&#xff0c;推测其基因组变异情况。 2. 数据准备 2.1 载入数据 library(Seurat) set…

C++:多态与虚函数

1.虚函数&#xff0c;在函数前加virtual即可。有虚函数时&#xff0c;父类指针指向父类对象时就会使用父类的成员&#xff0c;指向子类对象时就可以使用子类成员&#xff0c;进而我们引入了多态的概念。 2.多态&#xff1a;父类指针指向子类的对象&#xff0c;通过父类指针调用…

WSL下使用git克隆失败解决

WSL默认nat模式&#xff0c;别动了防火墙放行&#xff0c;见图1git导入[bash1]&#xff0c;ip为你wsl上linxu通过ifconfig获取的本机ip&#xff0c;端口对好某alcsh软件开启tun模式【经过测试&#xff0c;不开也行】应该成了&#xff0c;如果不行&#xff0c;修改.wslconfig为下…

开放鸿蒙OpenHarmony 5.0.0 Release 兼容性测试实战经验分享

OpenHarmony 5.0版本的发布时间是2024年12月20日至21日。这个版本带来了许多新特性和改进。现在5.0出了两个release 版本&#xff0c;分别是5.0.0和5.0.1。 就在5.0版本发布不到2周的时间内&#xff0c;2025年01月01日起&#xff0c;不支持新产品基于老分支&#xff08;OpenHar…

C++中explicit关键字的含义以及用法

在C中&#xff0c;explicit关键字用于修饰构造函数和转换运算符&#xff08;C11起&#xff09;&#xff0c;防止编译器进行隐式类型转换&#xff0c;要求必须显式调用构造函数或转换操作。以下是其核心用法和示例&#xff1a; 1. 修饰构造函数 用途 禁止隐式构造对象&#xf…

Oracle OCP认证考试考点详解083系列01

题记&#xff1a; 本系列主要讲解Oracle OCP认证考试考点&#xff08;题目&#xff09;&#xff0c;适用于19C/21C,跟着学OCP考试必过。 1. 第1题&#xff1a; 题目 解析及答案&#xff1a; 关于自动工作量存储库&#xff08;AWR&#xff09;快照&#xff0c;以下哪三个选项…

从DNS到TCP:DNS解析流程和浏览器输入域名访问流程

1 DNS 解析流程 1.1 什么是DNS域名解析 在生活中我们会经常遇到域名&#xff0c;比如说CSDN的域名www.csdn.net&#xff0c;百度的域名www.baidu.com,我们也会碰到IP&#xff0c;现在目前有的是IPV4&#xff0c;IPV6。那这两个有什么区别呢&#xff1f;IP地址是互联网上计算机…

《2025软件测试工程师面试》接口测试篇

基础概念 什么是接口测试? 接口测试是测试系统组件间接口的一种测试,主要用于检测外部系统和内部系统之间以及各个子系统之间的交互点。测试的重点是检查数据的交换、传递和控制管理的过程,以及系统间的相互逻辑依赖关系等。 接口测试的优势是什么? 接口测试具有规范性与扩…

【PHP脚本语言详解】为什么直接访问PHP文件会显示空白?从错误示例到正确执行!

前言 作为一名开发者&#xff0c;你是否曾经遇到过这样的问题&#xff1a;写了一个PHP脚本&#xff0c;放到服务器根目录后&#xff0c;直接通过file:///路径访问却显示空白页面&#xff1f;而换成http://localhost却能正常显示&#xff1f;这篇文章将带你深入理解PHP脚本语言…

word转换为pdf后图片失真解决办法、高质量PDF转换方法

1、安装Adobe Acrobat Pro DC 自行安装 2、配置Acrobat PDFMaker &#xff08;1&#xff09;点击word选项卡上的Acrobat插件&#xff0c;&#xff08;2&#xff09;点击“首选项”按钮&#xff0c;&#xff08;3&#xff09;点击“高级配置”按钮&#xff08;4&#xff09;点…