【题目大意】
求无向图点1到n的次短路。
【思路】
一年多前写过一次堆优化Dijkstra的,方法就是一边跑Dijsktra一边就把次短路径保存下来。和一般Dijkstra不同的是把vis数组去掉了,因为还要生成次短路径。戳这里☆
今天重新写用的是SPFA。正反跑两次SPFA,然后枚举每一条边,如果起点到一个端点的最短路+另一个端点到终点的最短路+长度 ≠ 最短路,则和答案比较,保存最小值。还是很好理解的:D
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int MAXR=100000+50; 4 const int MAXN=5000+50; 5 const int INF=0x7fffffff; 6 struct edge 7 { 8 int to; 9 int len; 10 }; 11 vector<edge> E[MAXN]; 12 int n,r,dis[MAXN],inque[MAXN],dis1[MAXN],dis2[MAXN]; 13 int u[MAXR],v[MAXR],w[MAXR]; 14 15 void addedge(int u,int v,int w) 16 { 17 E[u].push_back((edge){v,w}); 18 E[v].push_back((edge){u,w}); 19 } 20 21 void init() 22 { 23 scanf("%d%d",&n,&r); 24 for (int i=1;i<=r;i++) 25 { 26 scanf("%d%d%d",&u[i],&v[i],&w[i]); 27 addedge(u[i],v[i],w[i]); 28 } 29 } 30 31 void spfa(int S,int T) 32 { 33 for (int i=1;i<=n;i++) inque[i]=0,dis[i]=INF; 34 queue<int> que; 35 que.push(S); 36 inque[S]=1;dis[S]=0; 37 while (!que.empty()) 38 { 39 int head=que.front();que.pop(); 40 inque[head]=0; 41 for (int i=0;i<E[head].size();i++) 42 { 43 int nowdis=dis[head]+E[head][i].len,to=E[head][i].to; 44 if (nowdis<dis[to]) 45 { 46 dis[to]=nowdis; 47 if (!inque[to]) 48 { 49 que.push(to); 50 inque[to]=1; 51 } 52 } 53 } 54 } 55 } 56 57 void solve() 58 { 59 spfa(1,n); 60 for (int i=1;i<=n;i++) dis1[i]=dis[i]; 61 spfa(n,1); 62 for (int i=1;i<=n;i++) dis2 [i]=dis[i]; 63 int mx=dis1[n],ans=INF; 64 for (int i=1;i<=r;i++) 65 { 66 int now=dis1[u[i]]+dis2[v[i]]+w[i]; 67 if (now!=mx) ans=min(ans,now); 68 now=dis1[v[i]]+dis2[u[i]]+w[i]; 69 if (now!=mx) ans=min(ans,now); 70 } 71 printf("%d",ans); 72 } 73 74 int main() 75 { 76 init(); 77 solve(); 78 return 0; 79 }