求1到N的次短路,到某个顶点v的次短路有两种可能,一是到其他某个顶点u的最短路+edge(u,v)二是到其他某个点u的次短路+edge(u,v);
因此在松弛的时候不仅要记录最短路,同时也要记录次短路
#include<cstdio> #include<iostream> #include<algorithm> #include<vector> #include<cstring> #include<string> #include<queue> #define INF 1e6 using namespace std; const int maxn = 5005; struct node { int d,u; bool operator < (const node& rhs) const{ return d > rhs.d; } }; struct Edge { int from,to,dist; Edge(int u,int v,int d):from(u),to(v),dist(d){} }; int n,m; vector<Edge> edges;//保存边的信息 vector<int> g[maxn];//保存的边在edges数组里的编号; int d[maxn],d2[maxn];//最短距离,次短距离 void addedge(int from,int to,int dist)//跟刘汝佳学的。。 { edges.push_back((Edge){from,to,dist}); edges.push_back((Edge){to,from,dist}); int k = edges.size(); g[from].push_back(k-2); g[to].push_back(k-1); } void dijkstra(int s) { priority_queue<node> que; for(int i = 1; i <= n; ++i){ d[i] = d2[i]= INF;} d[s] = 0; que.push((node){0,s}); while(!que.empty()) { node x = que.top();que.pop(); int u = x.u; if(d2[u] < x.d) continue;//如果次短距离比这个节点的d值还小。。说明没有更新的必要 for(int i = 0; i < g[u].size(); ++i) { Edge& e = edges[g[u][i]]; int p = x.d + e.dist;//待更新的值,从这个节点进行松弛操作,注意这里的x.d可能是最短距离也可能是次短距离。 if(d[e.to] > p) { swap(d[e.to],p);//如果最短距离比这个P还大,那么要换一换这个值;这样可以省掉一些讨论 que.push((node){d[e.to],e.to}); } if(d2[e.to] > p&&d[e.to] < p)//这种p值介于最短与次短之间时要更新次短的距离。 { d2[e.to] = p; que.push((node){d2[e.to],e.to});//次短也可能对以后的结果有影响,所以也加入队列。 } } } } int main() { //freopen("in","r",stdin); scanf("%d%d",&n,&m); int from,to,dist; for(int i = 0; i < m; ++i) { scanf("%d%d%d",&from,&to,&dist); addedge(from,to,dist); } dijkstra(1); cout<<d2[n]<<endl; }