搬運自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; }