最短路预处理+枚举。
1到n的次短路长度必然等于 从1走到X的最短路+x到y的边权+y到n的最短路。
首先预处理好1到每一个节点的最短路,和n到每一个节点的最短路。
然后枚举每一条边作为中间边[x,y]或者[y,x],如果加起来长度是最短路则跳过,否则更新答案。
#include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<algorithm> using namespace std; const int INF=0x7FFFFFFF; const int maxn=5000+10; struct Edge { int u,v; int w; }e[200000+10]; int n,m; vector<int>g[maxn]; int dis[2][maxn]; bool flag[maxn]; void init() { for(int i=1;i<=n;i++) g[i].clear(); for(int i=1;i<=n;i++) dis[0][i]=dis[1][i]=INF; dis[0][1]=0; dis[1][n]=0; } void read() { for(int i=1;i<=m;i++) { scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w); g[e[i].u].push_back(i); e[i+m].u=e[i].v; e[i+m].v=e[i].u; e[i+m].w=e[i].w; g[e[i+m].u].push_back(i+m); } } void SPFA(int st) { queue<int>Q; memset(flag,0,sizeof flag); int now; if(st==1) now=0; else now=1; Q.push(st); flag[st]=1; while(!Q.empty()) { int head=Q.front(); Q.pop(); flag[head]=0; for(int i=0;i<g[head].size();i++) { int id=g[head][i]; int cost=e[id].w,to=e[id].v; if(dis[now][head]+cost<dis[now][to]) { dis[now][to]=dis[now][head]+cost; if(!flag[to]) {flag[to]=1;Q.push(to);} } } } } void work() { int f=dis[0][n]; int ans=INF; for(int i=1;i<=2*m;i++) { int u=e[i].u, v=e[i].v; if(dis[0][u]+e[i].w+dis[1][v]==f) continue; ans=min(dis[0][u]+e[i].w+dis[1][v],ans); } printf("%d ",ans); } int main() { while(~scanf("%d%d",&n,&m)) { init(); read(); SPFA(1); SPFA(n); work(); } return 0; }