图论03-【无权无向】-图的深度优先DFS遍历-路径问题/检测环/二分图

news2024/12/25 13:32:10

文章目录

  • 1. 代码仓库
  • 2. 单源路径
    • 2.1 思路
    • 2.2 主要代码
  • 3. 所有点对路径
    • 3.1 思路
    • 3.2 主要代码
  • 4. 路径问题的优化-提前结束递归
    • 4.1 思路
    • 4.2 主要代码
  • 5. 检测环
    • 5.1 思路
    • 5.2 主要代码
  • 6. 二分图
    • 6.1 思路
    • 6.2 主要代码
      • 6.2.1 遍历每个联通分量
      • 6.2.2 递归判断相邻两点的颜色是否一致

1. 代码仓库

https://github.com/Chufeng-Jiang/Graph-Theory

2. 单源路径

2.1 思路

  1. 构造visited数组和pre数组
    1.1 visited数组记录当前节点是否访问过
    也可以不使用visited数组,pre数组全部初始化为-1,联通的顶点对应的pre数组的值为前一个节点,pre数组中值为-1的都是不连通的顶点。
    1.2 pre数组记录当前节点的前一个节点
  2. 使用pre数组对终点进行反推回源点,并记录
  3. 将终点到原点的路径,反序输出

2.2 主要代码

   public SingleSourcePath(Graph G, int s){ //单源路径,要把源s传进来,而且只考虑与s连通的顶点,不连通的不考虑

        G.validateVertex(s);

        this.G = G;
        this.s = s;
        visited = new boolean[G.V()];
        pre = new int[G.V()];

        dfs(s, s);
    }

    private void dfs(int v, int parent){ //参数一:当前顶点; 参数二:上一个顶点

        visited[v] = true;
        pre[v] = parent;

        for(int w: G.adj(v)) //跟v相邻的所有顶点,相当于v是源,遍历与当前顶点相邻的所有点
            if(!visited[w])
                dfs(w, v); //(顶点,源)
    }
    
     public Iterable<Integer> path(int t){ //从源到t的路径

	     ArrayList<Integer> res = new ArrayList<Integer>();
	     if(!isConnectedTo(t)) return res;	
	     int cur = t; // 从t往回找
	     
	     while(cur != s){
	         res.add(cur); //添加当前节点(循环内不包含源)
	         cur = pre[cur]; //pre[cur]的值是cur的上一个节点
	     }
	     
	     res.add(s); //添加源
	     Collections.reverse(res);
	     return res;
 }

3. 所有点对路径

3.1 思路

对所有顶点进行遍历,创建每一个点的单源路径数组。

3.2 主要代码

public AllPairsPath(Graph G){
    this.G = G;
    paths = new SingleSourcePath[G.V()];
    for(int v = 0; v < G.V(); v ++)
        paths[v] = new SingleSourcePath(G, v);
}

4. 路径问题的优化-提前结束递归

4.1 思路

在填充visited和pre数组的时候,如果遇到了目标节点,直接结束。剩下的节点不进行处理。

if(v == t) return true; //程序出口,当到达t顶点时,返回true提前结束递归,而不仅仅是返回return

4.2 主要代码

    private boolean dfs(int v, int parent){

        visited[v] = true;
        pre[v] = parent;

        if(v == t) return true; //程序出口,当到达t顶点时,返回true提前结束递归,而不仅仅是返回return

        for(int w: G.adj(v)) //遍历与v相邻的顶点
            if(!visited[w]) //如果相邻的顶点没有被访问过
                if(dfs(w, v)) //递归遍历相邻的顶点,如果到达 v==t,则值为true
                    return true; //提前返回true

        return false; // 转一圈没法达到t,就可以返回false
    }

5. 检测环

5.1 思路

从某一点v出发,找到了点w,w被访问过,并且w不是v的前一个节点

5.2 主要代码

public CycleDetection(Graph G){
    this.G = G;
    visited = new boolean[G.V()];

    //要对所有的连通分量进行环检测
    for(int v = 0; v < G.V(); v ++)
        if(!visited[v])  //如果没有访问过
            if(dfs(v, v)){ //则进行深度搜索,如果深度搜索出来的是true,说明有环,则进入循环break
                hasCycle = true;
                break;
            }
}

    
private boolean dfs(int v, int parent){
    visited[v] = true;

    for(int w: G.adj(v))
        if(!visited[w]){ //case1:如果w没有被访问过
            if(dfs(w, v)) //如果dfs返回true,则说明有环。因为dfs有环才会返回true,那么进入if选择语句return true提前结束
                return true;
        }
        else if(w != parent) // case2:从v出发,找到了w,w还被访问过,并且w不是v的前一个节点
            return true; // 此时找到了环

    //其他的情况,找一圈没有找到环,返回false
    return false;
}

6. 二分图

在这里插入图片描述

6.1 思路

二分图可以通过染色过程把顶点区分开,
[-1:顶点还没染色]
[0:一种颜色]
[1:另外一种颜色]

6.2 主要代码

6.2.1 遍历每个联通分量

  1. dfs(v, 0) 返回true代表相连的两点颜色不一样,暂未出现矛盾;
  2. dfs(v, 0) 返回false代表相连的两点颜色一样,不符合二分图的定义,因此进入if语句块,设置isBipartite = false;并且提前结束循环。
for(int v = 0; v < G.V(); v ++)
    if(!visited[v]) //如果没有被访问
    // 起始的时候把v统一染成0色,如果dfs返回的false,进入下面结构体,否则跳出执行v++
        if(!dfs(v, 0)){ 
            isBipartite = false; // 检测出错了,就设置成false
            break; // 后续的循环就不需要进行了
        }

6.2.2 递归判断相邻两点的颜色是否一致

private boolean dfs(int v, int color){  //参数一:顶点   参数二:颜色
    visited[v] = true;
    colors[v] = color;

    //依次判断相邻顶点w的颜色
    for(int w: G.adj(v))
        if(!visited[w]){ //如果w没有被访问过,则进入判断
            if(!dfs(w, 1 - color)) //如果v的颜色是0,那么w的颜色应该是1。如果v的颜色是1,那么w的颜色应该是0.
                return false; //如果相邻的两个顶点颜色一样,那么就不是二分图
        }
        else if(colors[w] == colors[v]) //如果相邻的两个顶点颜色一样,那么就不是二分图
            return false;

        return true;
}

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

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

相关文章

java--Consumer的使用

一、目的 因为代码中用到了Consumer &#xff0c;所以特地来梳理其对应的用法以及总结。 二、介绍 Consumer 是一个函数式接口&#xff0c;它位于java.util.function 包中&#xff0c;它定义了一个名为accept 的抽象方法&#xff0c;该方法接受一个参数并且不返回任何结果。 …

【C++和数据结构】模拟实现哈希表和unordered_set与unordered_map

目录 一、哈希的概念与方法 1、哈希概念 2、常用的两个哈希函数 二、闭散列的实现 1、基本结构&#xff1a; 2、两种增容思路 和 插入 闭散列的增容&#xff1a; 哈希表的插入&#xff1a; 3、查找 4、删除 三、开散列的实现 1、基本结构 2、仿函数Hash 3、迭代器…

sealos 部署halo

首先创建数据库 postgresql 找到连接数据库&#xff0c;点击详情查看数据库的参数 部署halo应用 halohub/halo:2.5 高级配置里设置环境变量 本地存储 配置 Halo 环境变量环境变量 spring.sql.init.platformpostgresql spring.r2dbc.urlr2dbc:pool:postgresql://postgres:4w…

在 Python 中使用 Pillow 进行图像处理【3/4】

第三部分 一、腐蚀和膨胀 您可以查看名为 的图像文件dot_and_hole.jpg&#xff0c;您可以从本教程链接的存储库中下载该文件&#xff1a; 该二值图像的左侧显示黑色背景上的白点&#xff0c;而右侧显示纯白色部分中的黑洞。 侵蚀是从图像边界去除白色像素的过程。您可以通过使用…

运算符重载的三种实现方法

一、重载为一般函数 格式&#xff1a;返回类型 operator 运算符(参数列表) struct Complex{//定义一个复数结构&#xff1a;包括实部与虚部两部分 double real;//实部 double imag;//虚部 }; Complex operator(Complex c1,Complex c2){//对加法运算的重载&#xff1a;将运算符…

扩展字符串(acwing周赛第三题)

代码&#xff1a; #include <bits/stdc.h> using namespace std; typedef long long LL; const int N 1e510; const LL INF 2e18; LL len[N];string s"DKER EPH VOS GOLNJ ER RKH HNG OI RKH UOPMGB CPH VOS FSQVB DLMM VOS QETH SQB"; string a"DKER …

2023全新小程序广告流量主奖励发放系统源码 流量变现系统

2023全新小程序广告流量主奖励发放系统源码 流量变现系统 分享软件&#xff0c;吃瓜视频&#xff0c;或其他资源内容&#xff0c;通过用户付费买会员来变现&#xff0c;用户需要付费&#xff0c;有些人喜欢白嫖&#xff0c;所以会流失一部分用户&#xff0c;所以就写了这个系统…

TCP--滑动窗口

大家好&#xff0c;我叫徐锦桐&#xff0c;个人博客地址为www.xujintong.com。平时记录一下学习计算机过程中获取的知识&#xff0c;还有日常折腾的经验&#xff0c;欢迎大家来访。 接收端和发送端通过窗口来实现流量的控制。发送端维护一个发送窗口&#xff0c;接收端维护一个…

Selenium获取百度百科旅游景点的InfoBox消息盒

前面我讲述过如何通过BeautifulSoup获取维基百科的消息盒&#xff0c;同样可以通过Spider获取网站内容&#xff0c;最近学习了SeleniumPhantomjs后&#xff0c;准备利用它们获取百度百科的旅游景点消息盒&#xff08;InfoBox&#xff09;&#xff0c;这也是毕业设计实体对齐和属…

邻接表存储图或者树

大家好&#xff0c;我叫徐锦桐&#xff0c;个人博客地址为www.xujintong.com。平时记录一下学习计算机过程中获取的知识&#xff0c;还有日常折腾的经验&#xff0c;欢迎大家来访。 介绍 每个顶点都作为头节点&#xff0c;并且存在一个一维数组中h[N]。树就是相当于一种有向图…

进阶高级,接口+接口自动化测试疑难解答,一篇带你策底打通...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、你们做接口测试…

MapReduce编程:join操作和聚合操作

文章目录 MapReduce 编程&#xff1a;join操作和聚合操作一、实验目标二、实验要求及注意事项三、实验内容及步骤 附&#xff1a;系列文章 MapReduce 编程&#xff1a;join操作和聚合操作 一、实验目标 理解MapReduce计算框架的分布式处理工作流程掌握用mapreduce计算框架实现…

python调用astra进行人脸检测(使用CascadeClassifier)

1、简述 方法&#xff1a;使用opecv中&#xff0c;CascadeClassifier 级联分类器实现人脸检测&#xff0c;CascadeClassifier就是opencv下objdetect模块中用来做目标检测的级联分类器的一个类&#xff0c;它可以帮助我们检测例如车牌、眼睛、人脸等物体。它的大概原理就是判别…

C++17中std::string_view的使用

为了解决std::string初始化(或拷贝)成本高昂的问题&#xff0c;C17引入了std::string_view。std::string_view提供对现有字符串(C风格字符串、std::string、或另一个std::string_view)的只读访问&#xff0c;而无需进行拷贝。当想要有效地处理和操作字符串而不修改它们时&#…

用python计算积分

先安装这个包 pip install scipy运行 import tkinter as tk from scipy.integrate import quad# 创建主窗口 root tk.Tk() root.title("积分计算器")# 定义计算积分的函数 def calculate_integral():# 获取用户输入的函数表达式function function_entry.get()# 获…

2023年最全的外贸建站新手教程

凡做外贸的&#xff0c;我相信在过去几年中通过亚马逊、速卖通等电商平台上都取得了一定的成功。然而&#xff0c;近年来电商平台上的竞争激烈&#xff0c;利润空间有限&#xff0c;流量获取困难和昂贵&#xff0c;这对许多外贸从业者造成了困扰。因此&#xff0c;为了减少对平…

分析概览 文章管理 草稿管理 图片管理 站点管理 主站 关于 登出 手写操作系统项目----进程

大家好&#xff0c;我叫徐锦桐&#xff0c;个人博客地址为www.xujintong.com。平时记录一下学习计算机过程中获取的知识&#xff0c;还有日常折腾的经验&#xff0c;欢迎大家来访。 这里记录了&#xff0c;手写操作系统项目中关于进程的部分。 进程四要素 首先进程有四要素。 …

golang 八股文整理

目录 进程、线程、协程Go 的垃圾回收机制GC 的触发条件GC 的调优GMP 调度和 CSP 模型Goroutine 的调度原理Goroutine 的切换时机Context 结构原理Context 工作原理Context 使用场景Golang 的内存分配机制竞态问题内存逃逸golang 内存对齐机制golang 中 new 和 make 的区别&…

数二思维导图

高数上 第一章&#xff1a;函数、极限、连续 函数 函数的单调性、周期性、奇偶性复合函数 极限 求直接代入型的极限求∞∞型的极限用等价无穷小代换求00型的极限用洛必达法则求00型或∞∞型的极限求∞•0型的极限求幂指函数的极限函数的左右极限及需要求左右极限的情形极限的…

还不知道光场相机吗?

1.什么是光场&#xff1f; 光场&#xff08;light field&#xff09;&#xff1a;就是指光在每一个方向通过每一个点的光量。 从概念里&#xff0c;你至少可以得到两点信息&#xff1a; 光场包含光的方向光场包含一个点的光量 2.什么是光场相机 我们知道普通的相机拍照成像…