当前位置: 首页 > news >正文

次短路P2865 [USACO06NOV] Roadblocks G题解

上一篇讲了怎么找最短路,这一片讲一下怎么求次短路和怎么实现

先来看原版dijkstra求最短路

#include<bits/stdc++.h> 
#define mf(x,y) make_pair(x,y)//x距离,y节点 
using namespace std; 
int read(){int s=0,fl=1;char w=getchar();while(w>'9'||w<'0'){if(w=='-')fl=-1;w=getchar();}while(w<='9'&&w>='0'){s=s*10+(w^48);w=getchar();}return fl*s;
}
const int N=1000010;
int n,m,s,tot;
int head[N],ne[N],to[N],w[N];
void add(int x,int y,int ww){to[++tot]=y;ne[tot]=head[x];head[x]=tot;w[tot]=ww;  
}  
int d[N];
bool book[N];
void dj(int s){for(int i=1;i<=n;i++){d[i]=2147483647;}d[s]=0;priority_queue<pair<int,int> >q;q.push(mf(0,s)); // 将源点及其距离为0的信息加入队列  while(!q.empty()){  int x=q.top().second;q.pop(); // 取出距离最小的节点  if(book[x]){continue; // 如果节点已被访问过,则跳过 }book[x]=1; // 标记节点为已访问  for(int i=head[x];i;i=ne[i]){ // 遍历当前节点的所有邻接节点  int y=to[i]; // 邻接节点的编号if(d[y]>w[i]+d[x]){ // 如果通过当前节点可以找到更短的路径  d[y]=d[x]+w[i]; // 更新最短路径长度  q.push(mf(-d[y],y)); // 将邻接节点及其新的距离(取反后)加入队列  }}}
}
int main(){  n=read(),m=read(),s=read();for(int i=1,u,v,ww;i<=m;i++){u=read(),v=read(),ww=read();add(u,v,ww);}dj(s);for(int i=1;i<=n;i++){printf("%d ",d[i]);}cout<<endl;return 0; 
}

可以知道我们由d[i]表示到节点i的最短距离,遍历每一个节点来更新。这是找最短路

P2865 [USACO06NOV] Roadblocks G - 洛谷

首先,我们在用d数组记录最短路之外,还需要另一个数组sd来记录到节点i的次短路。更新逻辑是:

如果当前的举例大于最短路,也就是d[y],但是小于当前次短路sd[y],就用当前距离更新sd[y]。

如果当前最短路,也就是d[y]大于当前距离,就用之前的最短路去更新当前次短路,同时用当前距离去更新最短路

映射到代码里就是

for(int i=head[x];i;i=ne[i]){int y=to[i];int newd=dist+w[i];if(d[y]>newd){sd[y]=d[y];d[y]=newd;q.push(mf(-newd,y));}else if(sd[y]>newd&&d[y]<newd){sd[y]=newd;q.push(mf(-newd,y));}
}

AC代码:

#include<bits/stdc++.h>
#define mf(a,b) make_pair(a,b) 
using namespace std;
const int N=200100;
int read(){int s=0,fl=1;char w=getchar();while(w>'9'||w<'0'){if(w=='-')fl=-1;w=getchar();}while(w<='9'&&w>='0'){s=s*10+(w^48);w=getchar();}return fl*s;
}
void out(int x){if(x<0)putchar('-'),x=-x;if(x<10)putchar(x+'0');else out(x/10),putchar(x%10+'0');
}
int head[N],ne[N],to[N],w[N];
int d[N],sd[N];
int tot;
int n,r;
priority_queue<pair<int,int>>q;
void add(int x,int y,int v){to[++tot]=y;ne[tot]=head[x];head[x]=tot;w[tot]=v;
}
void dijkstra(){for(int i=1;i<=n;i++){d[i]=2e9+10;sd[i]=2e9+10;}q.push(mf(0,1));d[1]=0;while(!q.empty()){int x=q.top().second;int dist=-1*q.top().first;q.pop();if(dist>sd[x]){continue;}for(int i=head[x];i;i=ne[i]){int y=to[i];int newd=dist+w[i];if(d[y]>newd){sd[y]=d[y];d[y]=newd;q.push(mf(-newd,y));}else if(sd[y]>newd&&d[y]<newd){sd[y]=newd;q.push(mf(-newd,y));}}}
}
int main(){n=read();r=read();for(int i=1;i<=r;i++){int x=read();int y=read();int c=read();add(x,y,c);add(y,x,c);}dijkstra();cout<<sd[n];return 0;
}

http://www.lryc.cn/news/626902.html

相关文章:

  • KubeBlocks for ClickHouse 容器化之路
  • 【机器学习深度学习】AI大模型高并发挑战:用户负载部署策略
  • OceanBase DBA实战营2期--SQL 关键字限流学习笔记
  • Angular由一个bug说起之十八:伴随框架升级而升级ESLint遇到的问题与思考
  • 文本智能抽取:如何用NLP从海量文本中“炼“出真金?-告别无效阅读,让AI成为你的“信息炼金师
  • springboot--用户访问系统的增删改查记录
  • 静/动态库 IIC(arm) day58
  • Docker在Linux中安装与使用教程
  • 【Android】Serializable和Parcelable序列化对象:传递自定义类数据
  • 无人机抗噪模块技术概述!
  • AI + 金融领域 + 落地典型案例
  • AI +金融 = 七大核心维度+ 落地典型困难
  • 基于深度学习CenterPoint的3D目标检测部署实战
  • 《GPT-OSS 模型全解析:OpenAI 回归开源的 Mixture-of-Experts 之路》
  • 使用 FastAPI 的 WebSockets 和 Elasticsearch 来构建实时应用
  • shell脚本——搜索某个目录下带指定前缀的文件
  • 标准解读——71页2025《数字化转型管理 参考架构》【附全文阅读】
  • C++11中的互斥锁,条件变量,生产者-消费者示例
  • Cyberduck (FTP和SFTP工具) v9.2.3.43590
  • SpringBoot3后端项目介绍:mybig-event
  • 华为云之基于鲲鹏弹性云服务器部署openGauss数据库【玩转华为云】
  • 网页作品惊艳亮相!这个浪浪山小妖怪网站太治愈了!
  • AutoGLM2.0背后的云手机和虚拟机分析(非使用案例)
  • 百度地图 添加热区(Hotspot)
  • Ubuntu_22.04安装文档
  • 应用在运行时,向用户索取(相机、存储)等权限,未同步告知权限申请的使用目的,不符合相关法律法规要求--教你如何解决华为市场上架难题
  • 【数据库】Oracle学习笔记整理之六:ORACLE体系结构 - 重做日志文件与归档日志文件(Redo Log Files Archive Logs)
  • Ubuntu 虚拟显示器自动控制服务设置(有无显示器的切换)
  • 机器学习数据预处理总结(复习:Pandas, 学习:preprocessing)
  • iOS 应用迭代与上架节奏管理 从测试包到正式发布的全流程实践