二、搜索与图论6:Dijkstra 模板题+算法模板(Dijkstra求最短路 I, Dijkstra求最短路 II,1003 Emergency)

文章目录

  • 算法模板
    • Dijkstra题目代码模板
      • 朴素dijkstra算法
      • 堆优化版dijkstra
    • 树与图的存储
      • (1) 邻接矩阵:
      • (2) 邻接表:
      • 关于e[],ne[],h[]的理解
    • 关于堆的原理与操作
  • 模板题
    • Dijkstra求最短路 I
      • 原题链接
      • 题目
      • 思路
      • 题解
    • Dijkstra求最短路 II
      • 原题链接
      • 题目
      • 思路
      • 题解
    • 1003 Emergency
      • 原题链接
      • 题目
      • 思路
      • 题解

算法模板

在这里插入图片描述

Dijkstra题目代码模板

朴素dijkstra算法

对应模板题:Dijkstra求最短路 I
时间复杂是 O(n^2+m):n 表示点数,m 表示边数
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

int g[N][N];  // 存储每条边
int dist[N];  // 存储1号点到每个点的最短距离
bool st[N];   // 存储每个点的最短路是否已经确定// 求1号点到n号点的最短路,如果不存在则返回-1
int dijkstra()
{memset(dist, 0x3f, sizeof dist);dist[1] = 0;for (int i = 0; i < n - 1; i ++ ){int t = -1;     // 在还未确定最短路的点中,寻找距离最小的点for (int j = 1; j <= n; j ++ )if (!st[j] && (t == -1 || dist[t] > dist[j]))t = j;// 用t更新其他点的距离for (int j = 1; j <= n; j ++ )dist[j] = min(dist[j], dist[t] + g[t][j]);st[t] = true;}if (dist[n] == 0x3f3f3f3f) return -1;return dist[n];
}

堆优化版dijkstra

对应模板题:Dijkstra求最短路 II
时间复杂度 O(mlogn):n 表示点数,m 表示边数
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

typedef pair<int, int> PII;int n;      // 点的数量
int h[N], w[N], e[N], ne[N], idx;       // 邻接表存储所有边
int dist[N];        // 存储所有点到1号点的距离
bool st[N];     // 存储每个点的最短距离是否已确定// 求1号点到n号点的最短距离,如果不存在,则返回-1
int dijkstra()
{memset(dist, 0x3f, sizeof dist);dist[1] = 0;priority_queue<PII, vector<PII>, greater<PII>> heap;heap.push({0, 1});      // first存储距离,second存储节点编号while (heap.size()){auto t = heap.top();heap.pop();int ver = t.second, distance = t.first;if (st[ver]) continue;st[ver] = true;for (int i = h[ver]; i != -1; i = ne[i]){int j = e[i];if (dist[j] > distance + w[i]){dist[j] = distance + w[i];heap.push({dist[j], j});}}}if (dist[n] == 0x3f3f3f3f) return -1;return dist[n];
}

树与图的存储

树是一种特殊的图,与图的存储方式相同。
对于无向图中的边ab,存储两条有向边a->b, b->a。
因此我们可以只考虑有向图的存储。

(1) 邻接矩阵:

g[a][b] 存储边a->b

(2) 邻接表:

https://www.acwing.com/video/21/
(1:20:00左右)

// 对于每个点k,开一个单链表,存储k所有可以走到的点。h[k]存储这个单链表的头结点
int h[N], e[N], ne[N], idx;// 添加一条边a->b
void add(int a, int b)
{e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}int main(){...// 初始化idx = 0;memset(h, -1, sizeof h);...
}

有权重时模板:

int h[N],w[N],e[N],ne[N],idx; void add(int a,int b,int c){e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++;
}

关于e[],ne[],h[]的理解

在这里插入图片描述
h[N] : 表示 第 i 个节点的 第一条边的 idx
ne[M] : 表示 与 第 idx 条边 同起点 的 下一条边 的 idx
e[M] : 表示 第idx 条边的 终点

N : 节点数量
M:边的数量
i : 节点的下标索引
idx : 边的下标索引
变量初始化定义:

int h[N], e[M], ne[M], idx;

当我们加入一条边的时候:

void add(int a,int b){e[idx] = b;      // 记录 加入的边 的终点节点ne[idx] = h[a]; // h[a] 表示 节点 a 为起点的第一条边的下标,ne[idx] = h[a] 表示把 h[a] 这条边接在了 idx 这条边的后面,其实也就是把 a 节点的整条链表 接在了 idx 这条边 后面;目的就是为了下一步 把 idx 这条边 当成 a 节点的单链表的 第一条边,完成把最新的一条边插入到 链表头的操作;h[a] = idx++; // a节点开头的第一条边置为当前边,idx移动到下一条边
}

要注意的是邻接表插入新节点时使用的是“头插”,如图中节点2:当插入2 1时此时为2—>1, 而后插入2 4后,此时为 2—> 4 —> 1.
在这里插入图片描述

关于堆的原理与操作

二、数据结构10:堆 模板题+算法模板(堆排序,模拟堆)

模板题

Dijkstra求最短路 I

原题链接

https://www.acwing.com/problem/content/851/

题目

给定一个 n
个点 m
条边的有向图,图中可能存在重边和自环,所有边权均为正值。

请你求出 1
号点到 n
号点的最短距离,如果无法从 1
号点走到 n
号点,则输出 −1

输入格式
第一行包含整数 n
和 m

接下来 m
行每行包含三个整数 x,y,z
,表示存在一条从点 x
到点 y
的有向边,边长为 z

输出格式
输出一个整数,表示 1
号点到 n
号点的最短距离。

如果路径不存在,则输出 −1

数据范围
1≤n≤500
,
1≤m≤105
,
图中涉及边长均不超过10000。

输入样例:

3 3
1 2 2
2 3 1
1 3 4

输出样例:

3

思路

在这里插入图片描述
在这里插入图片描述

题解

#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
const int N = 510;
const int M = 1e5 + 10;
int dist[N]; // 存各点与1号点的最短距离 
bool st[N]; // 存各点是否已被 处理为最短距离点 判断 (当前已确定最短距离的点) 
int g[N][N];
int n,m,t;int dijkstra(){memset(dist,0x3f,sizeof dist);dist[1] = 0;for(int i = 0;i<n;i++){t = -1; //	t: 不在 当前已确定最短距离的点 中的距离最短的点 初始化为-1 for(int j = 1;j<=n;j++){if(!st[j] && (t == -1 || dist[t] > dist[j])){t = j;}}st[t] = true;for(int j=1;j<=n;j++){dist[j] = min(dist[j],dist[t] + g[t][j]); //用(1到t+t到j)的长度与(1到j)的长度进行对比更新 }}if(dist[n] == 0x3f3f3f3f) return -1;else return dist[n];
}
int main(){cin>>n>>m;memset(g,0x3f,sizeof g);for(int i=0;i<m;i++){int x,y,z;cin>>x>>y>>z;g[x][y] = min(g[x][y],z);}	int res = dijkstra();printf("%d",res);return 0;}

Dijkstra求最短路 II

原题链接

https://www.acwing.com/problem/content/852/

题目

给定一个 n
个点 m
条边的有向图,图中可能存在重边和自环,所有边权均为非负值。

请你求出 1
号点到 n
号点的最短距离,如果无法从 1
号点走到 n
号点,则输出 −1

输入格式
第一行包含整数 n
和 m

接下来 m
行每行包含三个整数 x,y,z
,表示存在一条从点 x
到点 y
的有向边,边长为 z

输出格式
输出一个整数,表示 1
号点到 n
号点的最短距离。

如果路径不存在,则输出 −1

数据范围
1≤n,m≤1.5×105
,
图中涉及边长均不小于 0
,且不超过 10000

数据保证:如果最短路存在,则最短路的长度不超过 109

输入样例:

3 3
1 2 2
2 3 1
1 3 4

输出样例:

3

思路

使用堆优化,选择用stl中的priority_queue进行操作
在这里插入图片描述
关于st[N]数组 处理冗余部分
https://www.acwing.com/solution/content/167860/

题解

#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
const int M = 2e5 + 10;
typedef pair<int,int> PII;
int dist[N]; // 存各点与1号点的最短距离 
bool st[N]; // 存各点是否已被 处理为最短距离点 判断 (当前已确定最短距离的点) 
//int g[N][N];
//堆优化中,由于为稀疏图,因此使用邻接表进行存储
int h[N],w[N],e[N],ne[N],idx; int n,m,t;//邻接表插入处理 
void add(int a,int b,int c){e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++;
}int dijkstra(){memset(dist,0x3f,sizeof dist);dist[1] = 0;//	堆优化版dijkstrapriority_queue<PII,vector<PII>,greater<PII>> heap;heap.push({0,1}); // {距离,编号}编号为1的点距离为0,表示1到1的距离为0 while(heap.size()){auto t = heap.top();heap.pop();int ver = t.second, distance = t.first; // distance :结点1到结点ver的距离if(st[ver]) continue;  // 冗余的话跳过st[ver] = true;for(int i=h[ver]; i!=-1; i=ne[i]){ // 邻接表遍历,从h[ver]开始遍历可达的所有结点int j = e[i];//			w[i]:结点ver到结点j的距离if(dist[j]>distance + w[i]){ // 1--->i的距离 和 1--->ver--->i的距离相比dist[j] = distance + w[i]; heap.push({dist[j],j});}} }if(dist[n] == 0x3f3f3f3f) return -1;else return dist[n];
}
int main(){cin>>n>>m;
//	memset(g,0x3f,sizeof g);memset(h,-1,sizeof h);;for(int i=0;i<m;i++){int x,y,z;cin>>x>>y>>z;add(x,y,z);}	int res = dijkstra();printf("%d",res);return 0;}

1003 Emergency

原题链接

原题链接

题目

题目大意:n个城市m条路,每个城市有救援小组,所有的边的边权已知。给定起点和终点,求从起点到终点的最短路径条数以及最短路径上的救援小组数目之和。如果有多条就输出点权(城市救援小组数目)最大的那个

思路

用一遍Dijkstra算法,救援小组个数相当于点权,用Dijkstra求边权最小的最短路径的条数,以及这些最短路径中点权最大的值
dis[i]表示从出发点到i结点最短路径的路径长度,
num[i]表示从出发点到i结点最短路径的条数,
w[i]表示从出发点到i点救援队的数目之和
当判定dis[u] + e[u][v] < dis[v]的时候,
不仅仅要更新dis[v],还要更新num[v] = num[u], w[v] = weight[v] + w[u];
如果dis[u] + e[u][v] == dis[v],还要更新num[v] += num[u],而且判断一下是否权重w[v]更小,如果更小了就更新w[v] = weight[v] + w[u];

题解

基于上述朴素版dijkstra进行改进,

#include <bits/stdc++.h>
using namespace std;
//题目大意:n个城市m条路,每个城市有救援小组,所有的边的边权已知。给定起点和终点,求从起点到终点的最短路径条数以及最短路径上的救援小组数目之和。如果有多条就输出点权(城市救援小组数目)最大的那个~
//
//分析:用一遍Dijkstra算法~救援小组个数相当于点权,用Dijkstra求边权最小的最短路径的条数,以及这些最短路径中点权最大的值~dis[i]表示从出发点到i结点最短路径的路径长度,num[i]表示从出发点到i结点最短路径的条数,w[i]表示从出发点到i点救援队的数目之和~当判定dis[u] + e[u][v] < dis[v]的时候,不仅仅要更新dis[v],还要更新num[v] = num[u], w[v] = weight[v] + w[u]; 如果dis[u] + e[u][v] == dis[v],还要更新num[v] += num[u],而且判断一下是否权重w[v]更小,如果更小了就更新w[v] = weight[v] + w[u]; const int N = 510;
int g[N][N];
int c1,c2;
int dist[N]; //dist[i]表示从出发点到i结点最短路径的路径长度
int weight[N]; //每个城市救援队数量
int w[N]; //w[i]表示从出发点到i点救援队的数目之和
bool st[N]; 
int num[N]; //num[i]表示从出发点到i结点最短路径的条数int n,m;void dij(){w[c1] = weight[c1];memset(dist,0x3f,sizeof dist);dist[c1] = 0;num[c1] = 1;int t;for(int i=0;i<n;i++){t = -1;for(int j=0;j<n;j++){if(!st[j] && (t==-1 || dist[t] >dist[j]) ){t = j;}}st[t] = true;for(int j=0;j<n;j++){
//			dist[j] = min(dist[j],dist[t] + g[t][j]);if(dist[j]>dist[t]+g[t][j]){ //当判定dis[u] + e[u][v] < dis[v]的时候,不仅仅要更新dis[v],还要更新num[v] = num[u], w[v] = weight[v] + w[u]; dist[j] = dist[t]+g[t][j];num[j] = num[t];w[j] = w[t] + weight[j];  
//				cout<<t<<" "<<w[t]<<endl;
//				w[j]+=weight[t];}else if(dist[j]==dist[t]+g[t][j]){ //如果dis[u] + e[u][v] == dis[v],还要更新num[v] += num[u],而且判断一下是否权重w[v]更小,如果更小了就更新w[v] = weight[v] + w[u]; num[j] = num[t]+num[j];if(w[t]+weight[j] > w[j]){w[j] = w[t] + weight[j];}}	}}//	return w[c2];	
}
int main(){cin>>n>>m>>c1>>c2;for(int i=0;i<n;i++){int t;cin>>t;weight[i] = t;}memset(g,0x3f,sizeof g); // 赋值无穷大 for(int i=0;i<m;i++){int x,y,z;cin>>x>>y>>z;g[x][y] = g[y][x] = z; // 无向图!所以存双向信息 }dij();cout<<num[c2]<<" "<<w[c2];
} 

参考链接:1003. Emergency (25)-PAT甲级真题(Dijkstra算法)

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

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

相关文章

05|Oracle学习(UNIQUE约束)

1. UNIQUE约束介绍 也叫&#xff1a;唯一键约束&#xff0c;用于限定数据表中字段值的唯一性。 1.1 UNIQUE和primary key区别&#xff1a; 主键/联合主键每张表中只有一个。UNIQUE约束可以在一张表中&#xff0c;多个字段中存在。例如&#xff1a;学生的电话、身份证号都是…

AWS——01篇(AWS入门 以及 AWS之EC2实例及简单实用)

AWS——01篇&#xff08;AWS入门 以及 AWS之EC2实例及简单实用&#xff09; 1. 前言2. 创建AWS账户3. EC23.1 启动 EC2 新实例3.1.1 入口3.1.2 设置名称 选择服务3.1.3 创建密钥对3.1.4 网络设置——安全组3.1.4.1 初始设置3.1.4.2 添加安全组规则&#xff08;开放新端口&…

尝试多数据表 sqlite

C 唯一值得骄傲的地方就是 通过指针来回寻址 &#x1f602; 提高使用的灵活性 小脚本buff 加成

Windows用户如何将cpolar内网穿透配置成后台服务,并开机自启动?

Windows用户如何将cpolar内网穿透配置成后台服务&#xff0c;并开机自启动&#xff1f; 文章目录 Windows用户如何将cpolar内网穿透配置成后台服务&#xff0c;并开机自启动&#xff1f;前置准备&#xff1a;VS Code下载后&#xff0c;默认安装即可VS CODE切换成中文语言 1. 将…

uni-app选择器( uni-data-picker)选择任意级别

背景说明 uni-app 官方的插件市场有数据驱动选择器&#xff0c;可以用作多级分类的场景。引入插件后&#xff0c;发现做不到只选择年级&#xff0c;不选择班级&#xff08;似乎&#xff0c;只能到最后子节点了&#xff09;。 需求中&#xff0c;有可能选择的不是叶子。比如&a…

适应于Linux系统的三种安装包格式 .tar.gz、.deb、rpm

deb、rpm、tar.gz三种Linux软件包的区别 rpm包-在红帽LINUX、SUSE、Fedora可以直接进行安装&#xff0c;但在Ubuntu中却无法识别&#xff1b; deb包-是Ubuntu的专利&#xff0c;在Ubuntu中双击deb包就可以进入自动安装进程&#xff1b; tar.gz包-在所有的Linux版本中都能使用…

2023 8-2 ~ 8-3

2181 合并0之间的节点 思路挺简单 就是注意一下指针不要制空 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* ListNod…

【Docker】Docker+Zipkin+Elasticsearch+Kibana部署分布式链路追踪

文章目录 1. 组件介绍2. 服务整合2.1. 前提&#xff1a;安装好Elaticsearch和Kibana2.2. 再整合Zipkin 点击跳转&#xff1a;Docker安装MySQL、Redis、RabbitMQ、Elasticsearch、Nacos等常见服务全套&#xff08;质量有保证&#xff0c;内容详情&#xff09; 本文主要讨论在Ela…

opencv rtsp 硬件解码

讨论使用opencv的reader 硬件解码的方案有太多种&#xff0c;如果使用ffmpeg硬件解码是最方便的&#xff0c;不方便的是把解码过后的GPU 拉到 CPU 上&#xff0c;再使用opencv的Mat 从cpu 上上载到gpu上&#xff0c;是不是多了两个过程&#xff0c;应该是直接从GPU mat 直接去…

数实融合 产业共创 | 竹云受邀出席“2023湾区数字科技50人论坛”

7月29日&#xff0c;“2023湾区数字科技50人论坛”在深圳湾科技生态园圆满举行&#xff01;本届论坛由深圳市科学技术协会指导&#xff0c;中国鲲鹏产业源头创新中心、湾盟产业创新服务中心主办&#xff0c;深圳市金融攻关基地、广东赛迪工业和信息化研究院、香港科技大学深港协…

MySQL数据库备份与恢复

在任何数据库环境中&#xff0c;总会有不确定的意外情况发生&#xff0c;比如停电&#xff0c;计算机系统的各种软硬件故障&#xff0c;认为破坏&#xff0c;管理员误操作等是不可避免的&#xff0c;这些情况可能会导致 数据的丢失&#xff0c; 服务器瘫痪 等严重后果。存在多个…

STM32CubeMX配置定时器PWM--保姆级教程

———————————————————————————————————— ⏩ 大家好哇&#xff01;我是小光&#xff0c;嵌入式爱好者&#xff0c;一个想要成为系统架构师的大三学生。 ⏩最近在开发一个STM32H723ZGT6的板子&#xff0c;使用STM32CUBEMX做了很多驱动&#x…

【Python】从同步到异步多核:测试桩性能优化,加速应用的开发和验证

目录 测试工作中常用到的测试桩mock能力 应用场景 简单测试桩 http.server扩展&#xff1a;一行命令实现一个静态文件服务器 性能优化&#xff1a;使用异步响应 异步响应 能优化&#xff1a;利用多核 gunicorn 安装 gunicorn 使用 gunicorn 启动服务 性能优化&#…

/lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.28‘ not found

某项目中&#xff0c;我要给别人封装一个深度学习算法的SDK接口&#xff0c;运行在RK3588平台上&#xff0c;然后客户给我的交叉编译工具链是 然后我用他们给我的交叉编译工具链报下面的错误&#xff1a; aarch64-buildroot-linux-gnu-gcc --version /data/chw/aarch64/bin/cca…

使用idea实现git操作大全(在项目开发中遇到的实际情况

使用idea实现git操作大全&#xff08;在项目开发中遇到的实际情况&#xff09; 1.安装git插件2.在开发中切记拉一个自己的分支 1.安装git插件 2.在开发中切记拉一个自己的分支 选中需要拉的分支&#xff0c;右键该分支&#xff0c;选中new breach from “分支”&#xff0c;点…

Permute 3 for mac音视频格式转换

Permute是一款Mac平台上的媒体格式转换软件&#xff0c;由Chaotic Software开发。它可以帮助用户快速地将各种音频、视频和图像文件转换成所需格式&#xff0c;并提供了一些常用工具以便于用户进行编辑和处理。 Permute的主要特点包括&#xff1a; - 支持大量格式&#xff1a;支…

小程序安全性加固:如何保护用户数据和防止恶意攻击

第一章&#xff1a;引言 在当今数字化时代&#xff0c;移动应用程序的使用已经成为人们日常生活中的重要组成部分。小程序作为一种轻量级的应用程序形式&#xff0c;受到了广泛的欢迎。然而&#xff0c;随着小程序的流行&#xff0c;安全性问题也日益凸显。用户数据泄露和恶意攻…

flask中写一个基础的sqlHelper类

写一个SQLHelper类&#xff1a; from flask_sqlalchemy import SQLAlchemydb SQLAlchemy()class SQLHelper:staticmethoddef add(record):db.session.add(record)return SQLHelper.session_commit()staticmethoddef add_all(records):db.session.add_all(records)return SQLH…

STM32 DMA

DMA介绍 DMA&#xff0c;Direct Memory Access&#xff0c;即直接存储器访问。 DMA传输&#xff0c;将数据从一个地址空间复制到另一个地址空间。&#xff08;内存&#xff08;程序里定义的数组&#xff09;->外设&#xff08;串口、SPI等外设的数据寄存器&#xff09;、外…

【MySQL】DDL和DML

4&#xff0c;DDL:操作数据库 我们先来学习DDL来操作数据库。而操作数据库主要就是对数据库的增删查操作。 4.1 查询 查询所有的数据库 SHOW DATABASES; 运行上面语句效果如下&#xff1a; 上述查询到的是的这些数据库是mysql安装好自带的数据库&#xff0c;我们以后不要操…