一题带你写出图论算法模板!!!

这题是道基础的图论算法题目 

注释很重要!!!!!!!

在做这道题之前,我们先了解一下基础的图论算法吧!!!

 

1.floyd:

 

 这样可以求出所有点到任意一点的最短路径和距离

dijkstra:

最短路问题考察的是我们如何抽象成一个模型

图论的题侧重点在于抽象

难点在建图!!!!

2.朴素Dijstra算法

Dijkstra算法算是贪心思想实现的,首先把起点到所有点的距离存下来找个最短的,然后松弛一次再找出最短的,所谓的松弛操作就是,遍历一遍看通过刚刚找到的距离最短的点作为中转站会不会更近,如果更近了就更新距离,这样把所有的点找遍之后就存下了起点到其他所有点的最短距离

3.dijkstra算法(堆优化,c++直接用STL优先队列)

能使用的核心是堆中出来的点一定是最小的,且不会被更新的

4.spfa算法(没有负环就可以用)

可以用于适合dijkstra解决的问题

floyd方法:

class Solution {
public:int dist[1100][1100];void floyd(int n){//floyd本质是试点探测法for(int k = 0;k < n;k++)for(int i = 0;i < n;i++)for(int j = 0;j < n;j++){//试点探测dist[i][j] = min(dist[i][j],dist[i][k] + dist[k][j]);}}int ans[1110];int findTheCity(int n, vector<vector<int>>& edges, int distanceThreshold) {//这题一看求的就是多源最短路//计算出当前点到所有点的最短距离,小于distance距离的点加入到当前点的数组的中//多源最短路有floyd算法,最常用的算法//也可以用单源最短路算法spfa和dijkstra,bellmanford(一般不用,复杂度有点高)//1.dijkstra算出当前点到所有点的距离,小于distance距离的点加入到当前点的数组的中//再遍历下一个点,往返加入int m = edges.size();memset(dist,0x3f,sizeof(dist));//初始化为无穷,方便后续试点判断的时候,不把无穷的点加入//无向图for(int i = 0;i < m;i++){int a = edges[i][0];int b = edges[i][1];int c = edges[i][2];dist[a][b] = c;dist[b][a] = c;dist[a][a] = 0;dist[b][b] = 0;}floyd(n);int min_val = 0x3f3f3f3f;for(int i = 0;i < n;i++){cout<<i<<" ";for(int j = 0;j < n;j++){if(j == i) continue;if(dist[i][j] <= distanceThreshold) ans[i]++;}min_val = min(ans[i],min_val);cout<<ans[i]<<endl;}int res = -0x3f3f3f3f;for(int i = 0;i < n;i++){if(ans[i] == min_val && res < i) res = i;}return res;}
};

spfa方法:
 

class Solution {
public:int h[11100],w[11100],ne[11100],e[11100],idx = 0;int dist[11100];void add(int a,int b,int c){e[idx] = b,ne[idx] = h[a],w[idx] = c,h[a] = idx++;}queue<int> q;int st[1100];void spfa(int start){dist[start] = 0;q.push(start);//队列里放着要被更新的点,这个点要去松弛边st[start] = 1;while(!q.empty()){ auto t = q.front();q.pop();st[t] = 0;//该点出队更新其他点(松弛边)for(int i = h[t];i != -1;i = ne[i]){int b = e[i];int c = w[i];if(dist[b] > dist[t] + c){dist[b] = dist[t] + c;if(!st[b]) {q.push(b);//如果该点不在队列里面,并且连接该点的边又被更新,那么我们一定要加入到队列,再更新一次st[b] = 1;}}}}//题目没有负权边}int ans[1100];int findTheCity(int n, vector<vector<int>>& edges, int distanceThreshold) {memset(h,-1,sizeof(h));int m = edges.size();for(int i = 0;i < m;i++){int a = edges[i][0];int b = edges[i][1];int c = edges[i][2];add(a,b,c);add(b,a,c);}int min_val = 0x3f3f3f3f;for(int i = 0;i < n;i++){int start = i;memset(dist,0x3f,sizeof(dist));memset(st,0,sizeof(st));spfa(start);for(int j = 0;j < n;j++){if(j == start) continue;if(dist[j] <= distanceThreshold) ans[start]++;}cout<<start<<" "<<ans[start]<<endl;min_val = min(ans[start],min_val);}cout<<min_val<<endl;int res = -0x3f3f3f3f;for(int i = 0;i < n;i++){if(ans[i] == min_val && res < i) res = i;}return res;}
};

dijkstra方法:

class Solution {
public:int h[11100],w[11100],ne[11100],e[11100],idx = 0;int dist[11100];void add(int a,int b,int c){e[idx] = b,ne[idx] = h[a],w[idx] = c,h[a] = idx++;}//st数组保存的是已经被拿来更新过的点//我们每次取的就是,从未被更新过的点集中选出一个离更新过的点的点集(距离点集中的源点最近)最近的点//更新过的点的点集我们记为V,未更新过的点的点集记为Eint st[11000];void dijkstra(int start,int n){dist[start] = 0;for(int i = 0;i < n;i++){  int t = -1;for(int j = 0;j < n;j++){if(!st[j] && (t == -1 || dist[t] > dist[j])) //要拿出的点必须是未更新过的点集中的点,//并且是离V的点集(距离点集中的源点),也就是距离源点距离最短的点{t = j;}}st[t]  = 1;for(int i = h[t];i != -1;i = ne[i])//用t去更新邻边{int b = e[i];int c = w[i];dist[b] = min(dist[b],dist[t] + c); }}}int ans[1100];int findTheCity(int n, vector<vector<int>>& edges, int distanceThreshold) {memset(h,-1,sizeof(h));int m = edges.size();for(int i = 0;i < m;i++){int a = edges[i][0];int b = edges[i][1];int c = edges[i][2];add(a,b,c);add(b,a,c);}int min_val = 0x3f3f3f3f;for(int i = 0;i < n;i++){int start = i;memset(dist,0x3f,sizeof(dist));memset(st,0,sizeof(st));dijkstra(start,n);for(int j = 0;j < n;j++){if(j == start) continue;if(dist[j] <= distanceThreshold) ans[start]++;}cout<<start<<" "<<ans[start]<<endl;min_val = min(ans[start],min_val);}cout<<min_val<<endl;int res = -0x3f3f3f3f;for(int i = 0;i < n;i++){if(ans[i] == min_val && res < i) res = i;}return res;}
};

模板题:

#include <iostream>
//因为题目给出500个点,100000条边,说明是个稠密图
//所以我们用邻接矩阵去存储
//朴素dijkstra算法
//三步骤
//1.初始化dist[1] = 0,其余的为正无穷,可以用0x3f3f3f表示
//2for循环n次
//3.遍历dist数组,找到一个节点,找到一个距离最短的值,假设最短的值的节点为j
//每次从 「未求出最短路径的点」中 取出 距离距离起点 最小路径的点,并把这个最短路径的点标记
//4.遍历从i节点后继的所有节点,更新节点,例如i节点后面是j,如果dist[j] > dist[i] + w
//w:i到j的边的距离,那么就更新dist[j] = dist[i] + w;//1 3 4,1 3 4,1 3 4,重复循环完,1步骤是遍历所有节点 
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 510;
int n,m;
int g[N][N],dist[N];//g是邻接矩阵,dist表示起点到当前节点的最短距离,下标就是顶点
//又因为这里我们是带权的,权不一样,所以g二维数组里面的元素表示的是从前一个顶点到这个
//点的边权(距离),每行每列的下标都代表顶点,元素是边权,边权为0就是两顶点没边
bool st[N];//默认为false,找到这个点的最短路径的话,就标记下来,不用再找了
//算法模板中第一个节点实际上被再次遍历了同时初始化了下一层的所有节点距离
int dijkstra()
{dist[1] = 0;//源点的距离我们默认为1for(int i = 1;i <= n;i++){int t = -1;//因为dijkstra算法不适用于负权边,所以我们用这个判断可以把第一个点//加入for(int j = 1;j <= n;j++)//遍历数组找到从当前顶点直达的最小的路径//为什么可以直接找到直达的,因为我们初始化时,不可达到的距离我们设为正无穷//所以说每次最多能达到初始化过dist的下标,没初始化过的其实就不会去执行t = j了{if(!st[j] && (t == -1 || dist[t] > dist[j]))//后面的或号我们叫短路操作//dist[t] > dist[j]确保了不是直接连通的顶点不会去执行这条语句{t = j;}}st[t] = true;//算法模板中第一个节点实际上被再次遍历了同时初始化了下一层的所有节点距离for(int j = 1;j <=n;j++)//用t去更新最短距离,枚举经过确定t顶点到直达的顶点的距离//并初始化//0x3f3f3f确保了不会执行不是直达的,不过我们还是要遍历n次,可能他由t出发的直达的//边有n条,因为稠密图是假设起点是st那么st的出边可能就有n条边,那么遍历完需要n个起点//稀疏图假设起点是st,出边最多可能有n条边,但是因为n和m相同,所以我们只是o(N){dist[j] = min(dist[j],dist[t] + g[t][j]);}}if(dist[n] == 0x3f3f3f3f) return -1;else return dist[n];
}
int main()
{memset(dist,0x3f,sizeof dist);memset(g,0x3f,sizeof g);cin>>n>>m;for(int i = 0;i < m;i++){int a,b,c;cin>>a>>b>>c;g[a][b] = min(g[a][b],c);}printf("%d",dijkstra());return 0;
}

dijkstra(堆优化版)方法:

class Solution {
public:int h[11100],w[11100],ne[11100],e[11100],idx = 0;int dist[11100];void add(int a,int b,int c){e[idx] = b,ne[idx] = h[a],w[idx] = c,h[a] = idx++;}//st数组保存的是已经被拿来更新过的点//我们每次取的就是,从未被更新过的点集中选出一个离更新过的点的点集(距离点集中的源点最近)最近的点//更新过的点的点集我们记为V,未更新过的点的点集记为Eint st[11000];typedef pair<int,int> PII;priority_queue<PII,vector<PII>,greater<PII>> heap;void dijkstra_heap(int start,int n){dist[start] = 0;heap.push({0,start});while(!heap.empty()){auto t = heap.top();//选出距离源点最小的点,按照dist(距离)排序int dist_u = t.first;int u = t.second;heap.pop();//如果该点是已经之前更新过的点(已经选中去松弛过的点),那不能被松弛,跳过if(st[u]) continue;else st[u] = 1;for(int i = h[u];i != -1;i = ne[i]){int b = e[i];int c = w[i];if(dist[b] > dist[u] + w[i]){//如果该点被更新了,那么要再加入更新一下dist[b] = dist[u] +w[i];//因为该边被更新了,那么他的邻边也需要更新heap.push({dist[b],b});}}}}int ans[1100];int findTheCity(int n, vector<vector<int>>& edges, int distanceThreshold) {memset(h,-1,sizeof(h));int m = edges.size();for(int i = 0;i < m;i++){int a = edges[i][0];int b = edges[i][1];int c = edges[i][2];add(a,b,c);add(b,a,c);}int min_val = 0x3f3f3f3f;for(int i = 0;i < n;i++){int start = i;memset(dist,0x3f,sizeof(dist));memset(st,0,sizeof(st));dijkstra_heap(start,n);for(int j = 0;j < n;j++){if(j == start) continue;if(dist[j] <= distanceThreshold) ans[start]++;}min_val = min(ans[start],min_val);}cout<<min_val<<endl;int res = -0x3f3f3f3f;for(int i = 0;i < n;i++){if(ans[i] == min_val && res < i) res = i;}return res;}
};

模板题:

#include <iostream>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
typedef pair<int,int> pll;
const int N = 200010;
int h[N],e[N],ne[N],idx;
int n,m,w[N],dist[N];
bool st[N];
void add(int a,int b,int c)
{e[idx] = b,w[idx] = c,ne[idx] = h[a],h[a] = idx++;
}
int dijkstra_2()
{dist[1] = 0;//初始话为0priority_queue<pll,vector<pll>,greater<pll>> heap;//加入第一个heap.push({0,1});//左边是顶点,右边是起点到当前顶点的距离while(!heap.empty()){auto t =heap.top();//大根堆,拿出最小的heap.pop();int k = t.second,dis = t.first;//k代表当前顶点if(st[k]) continue;//如果枚举过了就不用在枚举了st[k] = true;//for(int i = h[k];i != - 1;i = ne[i])//枚举当前最短距离的顶点,找到最小的边,加入{int j = e[i];//找到当前顶点直达的顶点if(dist[j] > dist[k] + w[i])//初始化当前最短的顶点直达的边的距离{dist[j] = dist[k] + w[i];heap.push({dist[j],j});//把顶点和距离加入,优先队列会维护这个队列的}}}if(dist[n] == 0x3f3f3f3f) return 0;else return dist[n];
}
int main()
{cin>>n>>m;memset(h,-1,sizeof h);memset(dist,0x3f,sizeof dist);for(int i = 0;i < m;i++){int a,b,c;cin>>a>>b>>c;add(a,b,c);}if(dijkstra_2() == 0) printf("-1\n");else printf("%d",dijkstra_2());return 0;
}

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

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

相关文章

【java学习—十四】java动态代理(6)

文章目录 1. 相关概念2. 步骤3. 举例 问题&#xff1a; 假设一个java项目有100个java类&#xff0c;每个java有10个方法&#xff0c;这总共有1000个方法&#xff0c;现在有这样一个需求&#xff0c;需要在每个java方法加上2句话&#xff1a;在方法执行前输出这个方法开始执行&a…

Qt 线程串口

文章目录 ui设置创建线程函数初始串口run函数接收发送数据读取数据处理读取的数据写入数据写入启动的命令 主线程 ui设置 创建线程函数 #include <QObject> #include <QThread> #include <QSerialPort> #include <QSerialPortInfo>class SerialPort :…

【Python】Matplotlib-多张图像的显示

一&#xff0c;情景描述 大家在写论文或者实验报告的时候&#xff0c;经常会放多张图片或数据图像在一起形成对比。比如&#xff0c;我现在有一张经过椒盐噪声处理的图像&#xff0c;现在进行三种滤波&#xff0c;分别是均值&#xff0c;高斯&#xff0c;中值滤波&#xff0c;…

ElementUI表格el-table自适应高度(表头表尾固定不动)

ElementUI表格el-table自适应高度&#xff08;表头表尾固定不动&#xff09;&#xff0c;内容只在中间滚动&#xff0c;效果如图&#xff1a; 实现代码 <div class"mt-10" :style"{height:tableHeight}"><div class"operation-bar">…

VScode+python开发,多个解释器切换问题

内容&#xff1a;主要VScode使用多个解释器 环境准备 VScode编辑器&#xff0c;两个版本python解释器 python3.7.2 python3.11.6 问题&#xff1a; 目前我们的电脑安装了python3.7.2、python3.11.6两个解释器&#xff0c;在vscode编辑器中&#xff0c;无法切换解释器使用如…

【蓝桥杯软件赛 零基础备赛20周】第3周——填空题

报名明年4月蓝桥杯软件赛的同学们&#xff0c;如果你是大一零基础&#xff0c;目前懵懂中&#xff0c;不知该怎么办&#xff0c;可以看看本博客系列&#xff1a;备赛20周合集 20周的完整安排请点击&#xff1a;20周计划 文章目录 00. 2023年第14届参赛数据0. 上一周答疑1. 填空…

RequestContextHolder详解

最近遇到的问题是在service获取request和response,正常来说在service层是没有request的,然而直接从controlller传过来的话解决方法太粗暴,后来发现了SpringMVC提供的RequestContextHolder遂去分析一番,并借此对SpringMVC的结构深入了解一下,后面会再发文章详细分析源码 1.Reque…

anaconda中安装pytorch和TensorFlow环境并在不同环境中安装kernel

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

单链表的实现

CSDN主页&#xff1a;醋溜马桶圈_C语言进阶,初始C语言,数据结构-CSDN博客 Gitee主页&#xff1a;mnxcc (mnxcc) - Gitee.com 专栏&#xff1a;数据结构_醋溜马桶圈的博客-CSDN博客 目录 1.认识单链表 2.创建单链表 3.单链表的操作 3.1打印单链表 3.2开辟新空间 3.3尾插 3.4头插…

深入探讨Linux中的文本文件查看命令

目录 前言1 cat命令2 less命令3 more命令4 head命令5 tail命令6 总结 前言 在Linux系统中&#xff0c;文本文件是日常工作中不可或缺的一部分&#xff0c;无论是配置文件、日志文件还是代码文件&#xff0c;都需要用到文本文件查看命令。在本文中&#xff0c;我们将深入研究一…

AI创作系统ChatGPT源码+AI绘画系统+支持OpenAI DALL-E3文生图,可直接对话文生图

一、AI创作系统 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。新增支…

桶装水订水小程序app,线上预约订水更便捷

桶装水订水小程序app&#xff0c;线上预约订水更便捷。设置好地址&#xff0c;一键订水&#xff0c;工作人员送水到家。还能配送新鲜果蔬&#xff0c;绿色健康有保证。送水软件手机版&#xff0c;提供各种品牌桶装水&#xff0c;在线发起订水服务&#xff0c;由服务人员送水到家…

QT windows与linux之间sokcet通信中文乱码问题解决方法

QT windows与linux之间sokcet通信中文乱码问题解决方法 linux发送与接收都转码utf-8: tcpClient ->write( send_msg.toUtf8());//解决乱码&#xff0c;发送转码 接收&#xff1a; QByteArray buffer tcpClient->readAll(); if(!buffer.isEmpty()) { // ui->plain…

双十一买高画质投影仪,当贝F6还是极米H6?

如果你想购买一台4K画质的投影仪,那么在各大平台搜索“双十一最值得买的4K投影仪”时,一定会注意到当贝F6和极米H6这两个型号投影仪。个人认为当贝F6和极米H6都分别是当贝和极米两个品牌非常具有性价比的4K投影仪。那么到底哪一台更适合你。 首先放一张参数对比图,方便参数控研…

登上CMMLU性能评测榜单第一 四大维度解码夸克自研大模型

11月14日&#xff0c;拥有千亿参数的夸克自研大模型正式发布&#xff0c;立刻占据CMMLU榜单第一名。夸克大模型将应用于通用搜索、医疗健康、教育学习、职场办公等多个场景。性能方面&#xff0c;其整体水平已经超过GPT-3.5&#xff0c;其中在写作、考试等部分场景中可以超过GP…

OpenCV实现手势虚拟拖拽

前言&#xff1a; Hello大家好&#xff0c;我是Dream。 今天来学习一下如何使用OpenCV实现手势虚拟拖拽&#xff0c;欢迎大家一起前来探讨学习~ 一、主要步骤及库的功能介绍 1.主要步骤 要实现本次实验&#xff0c;主要步骤如下&#xff1a; 导入OpenCV库。通过OpenCV读取摄…

做决策、定战略、带团队:顶级高手常用的16个思维模型

01 做决策 1.沃伦巴菲特的双目标清单系统&#xff08;Two-List System&#xff09; 弗林特当了巴菲特的私人飞行员十年之久&#xff0c;还曾为美国四任总统开过飞机&#xff0c;但他在事业上依然有更多追求。有一次&#xff0c;他和巴菲特在探讨他的职业生涯目标时&#xff0…

容器化nacos部署并实现服务发现(gradle)

1.如何容器化部署mysql 2. 如何容器化部署nacos 为不暴露我的服务器地址&#xff0c;本文全部使用localhost来代替服务器地址&#xff0c;所有的localhost都应该调整为你自己的服务器地址。 为不暴露我的服务器地址&#xff0c;本文全部使用localhost来代替服务器地址&#x…

Libra R-CNN: Towards Balanced Learning for Object Detection(2019.4)

文章目录 AbstractIntroduction引入问题1&#xff09; Sample level imbalance2) Feature level imbalance3) Objective level imbalance进行解决贡献 Related Work&#xff08;他人的work&#xff0c;捎带与我们的对比&#xff09;Model architectures for object detection&a…

突发!奥特曼宣布暂停ChatGPT Plus新用户注册!

大新闻&#xff01;就在刚刚&#xff01; OpenAI的CEO Sam Altman宣布暂停ChatGPT Plus 新用户注册&#xff01; Sam Altman对此解释道&#xff1a; 由于OpenAI开发日后ChatGPT使用量的激增超出了我们的承受能力&#xff0c;我们希望确保每个人都有良好的体验。 您仍然可以在a…