由于次短路一定存在,则可知次短路一定是最短路中某一条边不走,然后回到最短路,而且只是一条边,两条边以上不走的话,就一定不会是次短路了(即以边换边才能使最小)。所以可以枚举每一条边,算出从起点到这条边起点的最短距离,以及从终点到这条边终点的最短距离,再加上这条边的权值,看是否是次短路(比最短路总权值大的最小权值的路径)
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include <map> #include <queue> #define Mod 1000000007 using namespace std; #define N 5007 vector<pair<int,int> > G[200005]; int ds[N],dt[N],vis[N]; int n,m,k; void SPFA(int s,int *d) { int i,u,v; queue<int> que; memset(vis,0,sizeof(vis)); d[s] = 0; vis[s] = 1; que.push(s); while(!que.empty()) { v = que.front(); que.pop(); vis[v] = 0; //边允许重复走 for(i=0;i<G[v].size();i++) { u = G[v][i].first; if(d[v] + G[v][i].second < d[u]) { d[u] = d[v] + G[v][i].second; if(!vis[u]) { vis[u] = 1; que.push(u); } } } } } int main() { int u,v,w; int res,tmp,i,j; while(scanf("%d%d",&n,&m)!=EOF) { for(i=0;i<n;i++) G[i].clear(); for(i=1;i<=n;i++) ds[i] = dt[i] = Mod; while(m--) { scanf("%d%d%d",&u,&v,&w); G[u].push_back(make_pair(v,w)); G[v].push_back(make_pair(u,w)); } SPFA(1,ds); SPFA(n,dt); res = Mod; for(i=1;i<=n;i++) for(j=0;j<G[i].size();j++) { u = i; v = G[i][j].first; w = G[i][j].second; tmp = ds[u] + dt[v] + w; if(tmp > ds[n] && res > tmp) res = tmp; } printf("%d ",res); } return 0; }