次短路&&P2865 [USACO06NOV] Roadblocks G题解

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

先来看原版dijkstra求最短路

cpp 复制代码
#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]大于当前距离,就用之前的最短路去更新当前次短路,同时用当前距离去更新最短路

映射到代码里就是

cpp 复制代码
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代码:

cpp 复制代码
#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;
}
相关推荐
budingxiaomoli20 分钟前
算法--滑动窗口(一)
数据结构·算法
带土11 小时前
6. C语言 共用体及typedef
c语言
王哈哈^_^1 小时前
【数据集】【YOLO】【目标检测】农作物病害数据集 11498 张,病害检测,YOLOv8农作物病虫害识别系统实战训推教程。
人工智能·深度学习·算法·yolo·目标检测·计算机视觉·1024程序员节
xier_ran1 小时前
邻接矩阵的 k 次幂意味着什么?从图论到路径计数的直观解释
算法·图论
-Excalibur-2 小时前
形象解释关于TCP/IP模型——层层封装MAC数据帧的过程
linux·c语言·网络·笔记·单片机·网络协议·tcp/ip
B站_计算机毕业设计之家2 小时前
预测算法:股票数据分析预测系统 股票预测 股价预测 Arima预测算法(时间序列预测算法) Flask 框架 大数据(源码)✅
python·算法·机器学习·数据分析·flask·股票·预测
想唱rap3 小时前
C++ list 类的使用
c语言·开发语言·数据结构·c++·笔记·算法·list
l1t3 小时前
利用DuckDB SQL求解集合数学题
数据库·sql·算法·集合·duckdb
yuyanjingtao3 小时前
CCF-GESP 等级考试 2024年9月认证C++四级真题解析
c++·算法·青少年编程·gesp·csp-j/s
光头闪亮亮3 小时前
curl库应用-c++客户端示例及golang服务端应用示例
c++·go