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

news2024/11/15 19:30:09

文章目录

  • 1. 代码仓库
  • 2. 单源路径
    • 2.1 思路
    • 2.2 主要代码
  • 3. 所有点对路径
    • 3.1 思路
    • 3.2 主要代码
  • 4. 路径问题的优化-提前结束递归
    • 4.1 思路
    • 4.2 主要代码
  • 5. 检测环
    • 5.1 思路
    • 5.2 主要代码
  • 5. 二分图
    • 5.1 思路
    • 5.2 主要代码
      • 5.2.1 遍历每个联通分量
      • 5.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 主要代码

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;
}

5. 二分图

在这里插入图片描述

5.1 思路

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

5.2 主要代码

5.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; // 后续的循环就不需要进行了
        }

5.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/1119551.html

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

相关文章

192:最近的系列思考2/犬岛APP 的使用理解

最近的一些契机&#xff0c;导致一些思考&#xff1a; ​ * 与产品经理意志相悖的产品* 与最初的设计定位不匹配的产品社交大牛的APP一上线就引来诸多关注&#xff0c;作为总设计的纯大大非常简明扼要的说明了这个APP的定位&#xff1a;给内涵&#xff08;含&#xff09;有趣的…

图论04-【无权无向】-图的广度优先遍历

文章目录 1. 代码仓库2. 广度优先遍历图解3.主要代码4. 完整代码 1. 代码仓库 https://github.com/Chufeng-Jiang/Graph-Theory 2. 广度优先遍历图解 3.主要代码 原点入队列原点出队列的同时&#xff0c;将与其相邻的顶点全部入队列下一个顶点出队列出队列的同时&#xff0c;将…

布尔盲注知识点

概念&#xff1a;布尔盲注一般适用于页面没有回显字段(不支持联合查询)&#xff0c;且web页面返回True 或者 false&#xff0c;构造SQL语句&#xff0c;利用and&#xff0c;or等关键字来其后的语句 true 、 false使web页面返回true或者false&#xff0c;从而达到注入的目的来获…

Python---练习:while循环案例:猜数字

需求&#xff1a; 计算机从1 ~ 10之间随机生成一个数字&#xff0c;然后提示输入数字&#xff0c;如果我们输入的数字与随机数相等&#xff0c;则提示恭喜你&#xff0c;答对了。如果输入的数字比随机数大&#xff0c;则提示&#xff0c;猜大了。反之&#xff0c;则提示猜小了…

晶振与晶体

文章目录 基础知识无源晶振 & 有源晶振 博文链接 基础知识 无源晶振 & 有源晶振 博文链接 晶振原理解析

在Vue中使用Mock.js虚拟接口数据实例详解

在Vue项目中使用Mock.js可以方便地模拟接口数据&#xff0c;用于前端开发和测试。Mock.js是一个生成随机数据的库&#xff0c;可以帮助我们快速构建虚拟接口数据。在本文中&#xff0c;我将通过一个实例来详细讲解在Vue中使用Mock.js虚拟接口数据的方法。 首先&#xff0c;我们…

H5前端开发——事件处理

H5前端开发——事件处理 在H5前端开发中,事件处理是非常重要的一部分。通过事件处理,可以实现对用户操作的响应和交互。以下是几种常见的事件处理方式: HTML事件处理: 在HTML标签上直接设定事件处理函数,如<button onclick="myFunction()">点击我</bu…

【每周一测】Java阶段三第二周学习

目录 1、以下哪个过程可以创建Class对象? 2、下列switch代码段输出结果是&#xff08;&#xff09; 3、redis的数据类型 4、⭐以下关于Servlet生命周期说法错误的是&#xff08; &#xff09; 5、⭐下面有关SPRING的事务传播特性&#xff0c;说法错误的是&#xff1f; 6…

自然语言处理---huggingface平台使用指南

1 huggingface介绍 Huggingface总部位于纽约&#xff0c;是一家专注于自然语言处理、人工智能和分布式系统的创业公司。他们所提供的聊天机器人技术一直颇受欢迎&#xff0c;但更出名的是他们在NLP开源社区上的贡献。Huggingface一直致力于自然语言处理NLP技术的平民化(democr…

数据结构 MapSet(搜索)

数据结构 Map&Set(搜索) 文章目录 数据结构 Map&Set(搜索)1. 搜索树1.1 概念1.2 初始构建1.3 操作-插入1.4 操作-查找1.5 操作-删除1.6 性能分析 2. 搜索介绍2.1 概念及场景2.2 模型 3. Map的使用3.1 关于Map的说明3.2 关于Map.Entry<K, V>的说明3.3 Map的常用方…

Hadoop3教程(三十一):(生产调优篇)异构存储

文章目录 &#xff08;157&#xff09;异构存储概述概述异构存储的shell操作 &#xff08;158&#xff09;异构存储案例实操参考文献 &#xff08;157&#xff09;异构存储概述 概述 异构存储&#xff0c;也叫做冷热数据分离。其中&#xff0c;经常使用的数据被叫做是热数据&…

寻找Windows API 原始字节(x64dbg)

首先我们将我们的木马移入x64dbg 第一种方法 通过命令寻找 disasm CreateRemoteThreadEx第二种方法 将调试器附加到kernelbase.dll后转到符号选项卡&#xff0c;最后&#xff0c;在搜索栏中&#xff0c;我们可以搜索CreateRemoteThreadEx函数并双击它以获取下列&#xff1a…

深度学习---神经网络基础

深度学习概述 机器学习是实现人工智能的一种途径&#xff0c;深度学习是机器学习的一个子集&#xff0c;深度学习是实现机器学习的一种方法。与机器学习算法的主要区别如下图所示&#xff1a; 传统机器学习算术依赖人工设计特征&#xff0c;并进行特征提取&#xff0c;而深度学…

java新特性流 stream01

案例描述 今天跟着黑马程序员的视频&#xff0c;完成“瑞吉外卖”项目的菜品信息管理模块的时候&#xff0c;遇到了一个比较陌生的写法 用到了Java8的新特性 stream().map((item) -> {}).collect() List<DishDto> collect records.stream().map((item) -> {DishDt…

Elasticsearch 8.9 Master节点处理请求源码

大家看可以看ElasticSearch源码&#xff1a;Rest请求与Master节点处理流程&#xff08;1&#xff09; 这个图非常好&#xff0c;下午的讲解代码在各个类和方法之间流转&#xff0c;都体现这个图上 一、Master节点处理请求的逻辑1、节点(数据节点)要和主节点进行通讯&#xff0…

H5随机短视频滑动版带打赏源码,可封装APP软件或嵌入式观看

H5随机短视频滑动版带打赏源码&#xff0c;可封装APP软件或嵌入式观看&#xff0c;网站引流必备源码&#xff01; 数据来源抖音和快手官方短视频链接&#xff0c;无任何违规内容&#xff01;可自行添加广告等等&#xff01; 手机端完美支持滑动屏幕观看&#xff08;向上或向右…

STM32不使用 cubeMX实现外部中断

这篇文章将介绍如何不使用 cubeMX完成外部中断的配置和实现。 文章目录 前言一、文件加入工程二、代码解析exti.cexti.hmain.c 注意&#xff1a;总结 前言 实验开发板&#xff1a;STM32F103C8T6。所需软件&#xff1a;keil5 &#xff0c; cubeMX 。实验目的&#xff1a;如何不…

【【萌新的FPGA学习之分频器的介绍】】

萌新的FPGA学习之分频器的介绍 分频器的介绍 分频就是生成一个新时钟&#xff0c;该新时钟的频率是原有时钟频率的整数分之一倍&#xff0c;新周期是原有周期的整数倍。再简单来说&#xff0c;让你手撕一个四分频电路&#xff0c;就是写代码生成一个周期是原来四倍的时钟&…

PMP的智慧(2) - 系统性思考及复杂性

PMP的智慧(2) - 系统性思考及复杂性 在2021年推出的第七版《管理专业知识体系指南》中&#xff0c;PMI在传统的过程和ITTO的基础上&#xff0c;重新增加了12大项目管理原则。 管家式管理 stewardship团队 team干系人 stakeholders价值 value系统思考 system thinking领导力 l…

Excel函数中单元格的引用方式

如下图在D列第一行输入sum(A1:C1)&#xff1b; 回车之后结果如下&#xff1b;先要输入等号&#xff0c;然后输入sum&#xff0c;以及左括号&#xff0c;这是调用了sum求和函数&#xff1b; A1表示A列第一行&#xff0c;C1表示C列第一行&#xff1b; A1:C1&#xff0c;中间是冒号…