题意:求无向图中起点到终点的次短路。
思路:用两次dijkstra,分别正向和反向遍历一边,求出到起点的最短路dis1[]和到终点的最短路dis2[],然后再枚举每一条边 $ u->v $ ,令
$ d = dis1[u] + dis2[y] + edge.w $ ,在满足 $ d<dis1[n] $ 的条件下求出最小的d即为次短路的长度。
Code:
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
//Mystery_Sky
//
#define M 1000100
struct Edge{
int to, w, next;
}edge[M];
int n, m;
int head[M], cnt, dis1[M], dis2[M], vis[M];
inline void add_edge(int u, int v, int w) {edge[++cnt].to = v; edge[cnt].w = w; edge[cnt].next = head[u]; head[u] = cnt;}
struct node{
int dis;
int pos;
inline bool operator <(const node &x)const{
return x.dis < dis;
}
};
priority_queue <node> Q;
inline void dijkstra()
{
dis1[1] = 0;
Q.push((node){0, 1});
while(!Q.empty()) {
node top = Q.top(); Q.pop();
int x = top.pos;
if(vis[x]) continue;
vis[x] = 1;
for(int i = head[x]; i; i = edge[i].next) {
int y = edge[i].to;
if(dis1[y] > dis1[x] + edge[i].w) {
dis1[y] = dis1[x] + edge[i].w;
if(!vis[y]) Q.push((node){dis1[y], y});
}
}
}
}
inline void dijkstra_1()
{
memset(vis, 0, sizeof(vis));
dis2[n] = 0;
Q.push((node){0, n});
while(!Q.empty()) {
node top = Q.top(); Q.pop();
int x = top.pos;
if(vis[x]) continue;
vis[x] = 1;
for(int i = head[x]; i; i = edge[i].next) {
int y = edge[i].to;
if(dis2[y] > dis2[x] + edge[i].w) {
dis2[y] = dis2[x] + edge[i].w;
if(!vis[y]) Q.push((node){dis2[y], y});
}
}
}
}
int main() {
scanf("%d %d", &n, &m);
for(int i = 1; i <= m; i++) {
int u, v, w;
scanf("%d %d %d", &u, &v, &w);
add_edge(u, v, w); add_edge(v, u, w);
}
for(int i = 1; i <= n; i++) dis1[i] = dis2[i] = 0x3f3f3f3f;
dijkstra();
dijkstra_1();
int ans = 0x3f3f3f3f;
for(int i = 1; i <= n; i++) {
for(int j = head[i]; j; j = edge[j].next) {
int y = edge[j].to;
int d = dis1[i] + dis2[y] + edge[j].w;
if(d < ans && d > dis1[n]) ans = d;
}
}
printf("%d
", ans);
return 0;
}