搬運自https://www.cnblogs.com/kylinbalck/p/9878969.html#%E6%AC%A1%E7%9F%AD%E8%B7%AF 作者:筮安
这是严格次短路。
考虑在什么情况下会更新最短路。
1、由父亲节点过来的距离小于最短路,那么当前最短路变成次短路,更新最短路
2、若当前距离不能更新最短路,但比次短路小,更新次短路
3、若从父亲节点过来的次短路能更新当前次短路,更新次短路
所以,求次短路只需要一遍SPFA在更新最短路的时候顺便更新次短路就好了
#include<cmath>
#include<queue>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
inline long long read(){
long long a=0; int f=0; char c=getchar();
while(c<'0'||c>'9') { f|=c=='-'; c=getchar(); }
while(c>='0'&&c<='9') { a=(a<<3)+(a<<1)+(c^48); c=getchar(); }
return f? -a:a;
}
int n,m,dis[2][5005],cnt,fir[5005],a,b;
//0:最短路 1:次短路
bool vis[5005],f;
struct edge{ int u,v,w,nxt; } e[200001];
void add(int x,int y,int z){
e[++cnt].u=x,e[cnt].v=y,e[cnt].w=z,e[cnt].nxt=fir[x],fir[x]=cnt;
}
void spfa(){
for(int i=2;i<=n;++i) dis[0][i]=dis[1][i]=0x3f3f3f3f;
queue<int> q;
q.push(1),dis[1][1]=0x3f3f3f3f,vis[1]=1;
while(!q.empty()){
int u=q.front(); q.pop(); vis[u]=0;
for(int i=fir[u],v;v=e[i].v,i;i=e[i].nxt){
f=0;
if(dis[0][v]>dis[0][u]+e[i].w) //第一种情況
dis[1][v]=dis[0][v],dis[0][v]=dis[0][u]+e[i].w,f=1;
if(dis[1][v]>dis[0][u]+e[i].w&&dis[0][v] != dis[0][u]+e[i].w) //第二种情況
dis[1][v]=dis[0][u]+e[i].w,f=1;
if(dis[1][v]>dis[1][u]+e[i].w) dis[1][v]=dis[1][u]+e[i].w,f=1; //第三种情況
if(!vis[v]&&f) {q.push(v),vis[v]=1;}
}
}
}
int main(){
n=read(),m=read();
for(int i=1,x,y,z;i<=m;++i)
x=read(),y=read(),z=read(),add(x,y,z),add(y,x,z);
spfa();
printf("%d",dis[1][n]);
return 0;
}