【代码随想录——图论——图论理论基础】

1. 图论理论基础

1.1 图的基本概念

二维坐标中,两点可以连成线,多个点连成的线就构成了图。

当然图也可以就一个节点,甚至没有节点(空图)

1.1.1 图的种类

  • 有向图
    • 加权有向图
    • 无权有向图
  • 无向图
    • 加权无向图
    • 无权无向图

1.1.2 度

  • 无向图的度
    • 无向图中连接节点的边数等于该节点的度数
  • 有向图的度
    • 出度:从该节点出发的边的个数
    • 入度:指向该节点边的个数

1.2 连通性

  • 无向图

    • 连通图
      • 在无向图中,任何两个节点都是可以到达的,我们称之为连通图
    • 非连通图
      • 如果有节点不能到达其他节点,则为非连通图
  • 有向图

    • 强连通图
      • 在有向图中,任何两个节点是可以相互到达的,我们称之为强连通图。
  • 连通分量

    • 无向图中的极大连通子图称之为该图的一个连通分量。
  • 强连通分量

    • 有向图中极大强连通子图称之为该图的强连通分量

1.3 图的构造

1.3.1 邻接矩阵

邻接矩阵 使用 二维数组来表示图结构。 邻接矩阵是从节点的角度来表示图,有多少节点就申请多大的二维数组。
在这里插入图片描述

  • 邻接矩阵的优点:
    • 表达方式简单,易于理解
    • 检查任意两个顶点间是否存在边的操作非常快
    • 适合稠密图,在边数接近顶点数平方的图中,邻接矩阵是一种空间效率较高的表示方法。
  • 缺点:
    • 遇到稀疏图,会导致申请过大的二维数组造成空间浪费且遍历边的时候需要遍历整个n * n矩阵,造成时间浪费

1.3.2 邻接表

邻接表使用数组 + 链表的方式来表示。 邻接表是从边的数量来表示图,有多少边才会申请对应大小的链表。
在这里插入图片描述

  • 邻接表的优点:
    • 对于稀疏图的存储,只需要存储边,空间利用率高
    • 遍历节点连接情况相对容易
  • 缺点:
    • 检查任意两个节点间是否存在边,效率相对低,需要 O(V)时间,V表示某节点连接其他节点的数量。
    • 实现相对复杂,不易理解

1.4 图的遍历方式

  • 深度优先搜索(dfs)
    • dfs是可一个方向去搜,不到黄河不回头,直到遇到绝境了,搜不下去了,再换方向(换方向的过程就涉及到了回溯)。
  • 广度优先搜索(bfs)
    • bfs是先把本节点所连接的所有节点遍历一遍,走到下一个节点的时候,再把连接节点的所有节点遍历一遍,搜索方向更像是广度,四面八方的搜索过程。

2. 深度优先搜索理论基础

2.1 代码模板

深度优先搜索策略一般上使用递归的方式来实现。

// 递归模板
void dfs(参数){处理节点dfs(图,选择的节点)//递归回溯,撤销处理结果
}
// 回溯法的代码框架
void backtracking(参数){if (终止条件){存放结果;return;}for (选择:本层集合中元素(树中节点孩子的数量就上集合的大小)){处理节点;backtracking(路径,选择列表);回溯,撤销处理结果}
}
//其实回溯代码的过程就上一个dfs的过程
void dfs(参数){if(终止条件){存放结果;return;}for (选择:本节点所连接的其他节点){处理节点;dfs(图,选择的节点);//递归回溯,撤销处理结果}
}

2.2 深搜三部曲

  1. 确认递归函数,参数
    一般情况,深搜需要 二维数组数组结构保存所有路径,需要一维数组保存单一路径,这种保存结果的数组,我们可以定义一个全局变量,避免让我们的函数参数过多。

    vector<vector<int>> result; // 保存符合条件的所有路径
    vector<int> path; // 起点到终点的路径
    void dfs (图,目前搜索的节点)  
    
  2. 确认终止条件

    if (终止条件) {存放结果;return;
    }
    
  3. 处理目前搜索节点出发的路径

    for (选择:本节点所连接的其他节点) {处理节点;dfs(图,选择的节点); // 递归回溯,撤销处理结果
    }
    

3. 广度优先搜索理论基础

  • 广搜的搜索方式就适合于解决两个点之间的最短路径问题。
  • 因为广搜是从起点出发,以起始点为中心一圈一圈进行搜索,一旦遇到终点,记录之前走过的节点就是一条最短路。
  • 广度搜索需要的仅仅需要一个容器,用来保存我们要遍历的元素即可

代码模板如下

int dir[4][2] = {0, 1, 1, 0, -1, 0, 0, -1}; // 表示四个方向
// grid 是地图,也就是一个二维数组
// visited标记访问过的节点,不要重复访问
// x,y 表示开始搜索节点的下标
void bfs(vector<vector<char>>& grid, vector<vector<bool>>& visited, int x, int y) {queue<pair<int, int>> que; // 定义队列que.push({x, y}); // 起始节点加入队列visited[x][y] = true; // 只要加入队列,立刻标记为访问过的节点while(!que.empty()) { // 开始遍历队列里的元素pair<int ,int> cur = que.front(); que.pop(); // 从队列取元素int curx = cur.first;int cury = cur.second; // 当前节点坐标for (int i = 0; i < 4; i++) { // 开始想当前节点的四个方向左右上下去遍历int nextx = curx + dir[i][0];int nexty = cury + dir[i][1]; // 获取周边四个方向的坐标if (nextx < 0 || nextx >= grid.size() || nexty < 0 || nexty >= grid[0].size()) continue;  // 坐标越界了,直接跳过if (!visited[nextx][nexty]) { // 如果节点没被访问过que.push({nextx, nexty});  // 队列添加该节点为下一轮要遍历的节点visited[nextx][nexty] = true; // 只要加入队列立刻标记,避免重复访问}}}
}

4. 所有可达路径

4.1 dfs邻接矩阵版本

package mainimport "fmt"// 地图数据
var m [][]int// 结果
var result [][]int// 路径
var path []intfunc main() {var N, M int_, err := fmt.Scanln(&N, &M)if err != nil {fmt.Println(2001)return}// 使用邻接矩阵存储地图信息m = make([][]int, N+1)for i := 0; i <= N; i++ {m[i] = make([]int, N+1)}var from, to intfor i := 0; i < M; i++ {_, err := fmt.Scanln(&from, &to)if err != nil {fmt.Println(2002)return}m[from][to] = 1}//初始化变量result = make([][]int, 0)path = make([]int, 0)//dfs递归path = append(path, 1)dfs(1, N)// 输出结果if len(result) == 0 {fmt.Println(-1)} else {printMatrix(result)}
}func dfs(now int, end int) {//终止条件if now == end {temp := make([]int, len(path))copy(temp, path)result = append(result, temp)return}//遍历for i := 1; i < len(m); i++ {if m[now][i] == 1 {path = append(path, i)dfs(i, end)path = path[:len(path)-1]}}
}func printMatrix(matrix [][]int) {for i := 0; i < len(matrix); i++ {printArray(matrix[i])}
}func printArray(arr []int) {for i := 0; i < len(arr); i++ {if i == 0 {fmt.Print(arr[i])} else {fmt.Printf(" %d", arr[i])}}fmt.Println()
}

4.2 dfs邻接表版本

package mainimport "fmt"// 地图数据
var m [][]int// 结果
var result [][]int// 路径
var path []intfunc main() {var N, M int_, err := fmt.Scanln(&N, &M)if err != nil {fmt.Println(2001)return}// 使用邻接表存储地图信息m = make([][]int, N+1)for i := 0; i <= N; i++ {m[i] = make([]int, 0)}var from, to intfor i := 0; i < M; i++ {_, err := fmt.Scanln(&from, &to)if err != nil {fmt.Println(2002)return}m[from] = append(m[from], to)}//初始化变量result = make([][]int, 0)path = make([]int, 0)//dfs递归path = append(path, 1)dfs(1, N)// 输出结果if len(result) == 0 {fmt.Println(-1)} else {printMatrix(result)}
}func dfs(now int, end int) {//终止条件if now == end {temp := make([]int, len(path))copy(temp, path)result = append(result, temp)return}//遍历for i := 0; i < len(m[now]); i++ {path = append(path, m[now][i])dfs(m[now][i], end)path = path[:len(path)-1]}
}func printMatrix(matrix [][]int) {for i := 0; i < len(matrix); i++ {printArray(matrix[i])}
}func printArray(arr []int) {for i := 0; i < len(arr); i++ {if i == 0 {fmt.Print(arr[i])} else {fmt.Printf(" %d", arr[i])}}fmt.Println()
}

4.4 结果分析

在这里插入图片描述
上面的是邻接表跑出来的结果,下面是邻接矩阵跑出来的结果。
相差不大只能说。(应该是测试用例的问题)

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

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

相关文章

.NET C# 使用OpenCV实现人脸识别

.NET C# 使用OpenCV实现模型训练、人脸识别 码图~~~ 1 引入依赖 OpenCvSHarp4 - 4.10.0.20240616 OpenCvSHarp4.runtime.win - 4.10.0.20240616 2 人脸数据存储结构 runtime directory | face | {id}_{name} | *.jpg id - 不可重复 name - 人名 *.jpg - 人脸照片3 Demo 3.…

松下Panasonic机器人维修故障原因

松下机器人伺服电机是许多工业自动化设备的关键组成部分。了解如何进行Panasonic工业机械臂电机维修&#xff0c;对于确保设备正常运行至关重要。 【松下焊接机器人维修案例】【松下机器人维修故障排查】 一、常见松下工业机械手伺服电机故障及原因 1. 过热&#xff1a;过热可…

vue2+element-ui新增编辑表格+删除行

实现效果&#xff1a; 代码实现 &#xff1a; <el-table :data"dataForm.updateData"border:header-cell-style"{text-align:center}":cell-style"{text-align:center}"><el-table-column label"选项字段"align"center&…

C++:求梯形面积

梯形面积 已知上底15厘米&#xff0c;下底25厘米&#xff0c;问梯形面积值是多少&#xff1f; #include<iostream> using namespace std; int main() {//梯形的面积公式&#xff08;上底下底&#xff09; 高 2//上底变量、下底变量int s,d,h,m;s15;d25;h 2*150 * 2/s ;…

相亲交友APP系统婚恋交友社交软件开发语音视频聊天平台定制开发-婚恋相亲交友软件平台介绍——app小程序开发定制

互联网飞速发展的时代&#xff0c;相亲交友软件成为了许多年轻人首选的相亲方式&#xff0c;越来越多的单身男女希望在婚恋交友软件平台上寻找灵魂伴侣&#xff0c;相亲交友软件因此具有很高的市场价值。 多客婚恋相亲交友系统是一款定位高端&#xff0c;到手就能运营的成熟婚恋…

Redis 管道(Pipeline)是什么?有什么用?

目录 1. redis 客户端-服务端模型的不足之处 2. redis 管道是什么&#xff1f;有什么好处&#xff1f; 3. 管道的使用场景 4. 管道使用的注意事项 1. redis 客户端-服务端模型的不足之处 众所周知&#xff0c;redis 是一个客户端-服务端的模型设计&#xff0c;客户端向服务…

SALOME源码分析:View Model

作为一款开源的CAx(CAD/CAE/CAM)软件集成平台&#xff0c;为了实现各个Module支持不同的数据显示与交互方案&#xff0c;出于扩展性的考虑&#xff0c;SALOME引入了View Model&#xff0c;用以支持OpenGL、OCC、VTK、ParaView、Qwt等数据显示与交互实现。 本文将以OCCViewer、…

一文搞懂 java 线程池:ScheduledThreadPool 和 WorkStealingPool 原理

你好&#xff0c;我是 shengjk1&#xff0c;多年大厂经验&#xff0c;努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注&#xff01;你会有如下收益&#xff1a; 了解大厂经验拥有和大厂相匹配的技术等 希望看什么&#xff0c;评论或者私信告诉我&#xff01; 文章目录 一…

PHP宜邦家政服务管理系统-计算机毕业设计源码04426

目 录 摘要 1 绪论 1.1 选题背景与意义 1.2开发现状 1.3论文结构与章节安排 2 宜邦家政服务管理系统系统分析 2.1 可行性分析 2.1.1 技术可行性分析 2.1.2 经济可行性分析 2.1.3 操作可行性分析 2.2 系统功能分析 2.2.1 功能性分析 2.2.2 非功能性分析 2.3 系统用…

力扣hot100 -- 动态规划(上)

目录 ❄技巧 &#x1f33c;爬楼梯 &#x1f354;杨辉三角 &#x1f30a;打家劫舍 &#x1f40e;完全平方数 &#x1f33c;零钱兑换 &#x1f33c;单词拆分 ❄技巧 动态规划dp-CSDN博客 &#x1f446;花 5 分钟快速刷一遍 花 10 分钟浏览一下 线性DP 背包DP&#x1f447…

VS展示6个错误中的0个解决方法

左键点击展示6个错误中的0个 左键点击展示23个警告中的0个

国产强大免费WAF, 社区版雷池动态防护介绍

雷池WAF&#xff0c;基于智能语义分析的下一代 Web 应用防火墙 使用情况 我司于2023年4月23日对雷池进行测试&#xff0c;测试一个月后&#xff0c;于2023年5月24日对雷池进行正式切换&#xff0c;此时版本为1.5.1。 里程碑纪念 后续一直跟随雷池进行版本升级&#xff0c;当前…

怎样使用js技术实现Chrome投屏功能?

在Web前端技术中&#xff0c;直接控制浏览器窗口或标签页从主屏投屏到副屏&#xff08;如PPT的演讲者模式&#xff09;并不简单&#xff0c;而且直接控制浏览器窗口从主屏投屏到副屏的功能超出了Web标准的范畴&#xff0c;并且涉及到用户系统级别的设置和权限&#xff0c;因此不…

ETCD概述--使用/特性/架构/原理

ETCD概述 ETCD是一个高度一致的分布式键值存储, 它提供了一种可靠的方式来存储需要由分布式系统或机器集群访问的数据(高可用, 强一致性)​全局的配置服务中心. 本文将介绍其特性、相关操作和常见的应用场景. 如果想了解更多, 请查阅我的技术博客: https://dingyuqi.com 特性 …

C语言分支和循环(下)

C语言分支和循环&#xff08;下&#xff09; 1. 随机数生成1.1 rand1.2 srand1.3 time1.4 设置随机数的范围 2. 猜数字游戏实现 掌握了前面学习的这些知识&#xff0c;我们就可以写⼀些稍微有趣的代码了&#xff0c;比如&#xff1a; 写⼀个猜数字游戏 游戏要求&#xff1a; 电…

git常用命令速查表

Git相关概念简述 版本库&#xff1a;git在本地开辟的一个存储空间&#xff0c;一般在 .git 文件里。工作区(workspace)&#xff1a; 就是编辑器里面的代码&#xff0c;我们平常开发直接操作的就是工作区。暂存区&#xff08;index/stage&#xff09;&#xff1a;暂时存放文件的…

13. Revit API: Filter(过滤器)

13. Revit API: Filter&#xff08;过滤器&#xff09; 前言 在讲Selection之前&#xff0c;还是有必要先了解一下的过滤器的。 对了&#xff0c;关于查找一些比较偏的功能或者API的用法&#xff0c;可以这样查找 关键词 site:https://thebuildingcoder.typepad.com/ site是…

C语言 -- 函数

C语言 -- 函数 1. 函数的概念2. 库函数2.1 标准库和头文件2.2 库函数的使用方法2.2.1 功能2.2.2 头文件包含2.2.3 实践2.2.4 库函数文档的一般格式 3. 自定义函数3.1 函数的语法形式3.2 函数的举例 4. 形参和实参4.1 实参4.2 形参4.3 实参和形参的关系 5. return 语句6. 数组做…

react ts 封装3D柱状图,支持渐变

留档&#xff0c;以防忘记 bar3D.tsx import React, { useEffect, useRef, useState } from react; import * as echarts from echarts; import echarts/lib/chart/bar; import echarts/lib/chart/pictorialBar; import echarts/lib/component/grid; import echarts/lib/comp…

Centos7 安装老版本的chrome

查看自己linux是哪个centos版本 使用以下命令&#xff1a; cat /etc/centos-release我这里是centOS 7。然后在安装最新版的google-chrome时&#xff0c;总是会报错显示存在依赖环境的问题&#xff0c;使得无法安装成功chrome。 Package: google-chrome-stable (/google-chro…