寻找次短路。
令dis[]为点到源点的最小距离,dist[]为点到终点的最小距离。
由此可知dis[u] + dist[u]为从源点到终点的最短路。
dis[u] + cost[u][v] + dist[v]表示源点通过uv边到终点,次短路一定是其中比最短路大比其他路小的值。
因此只要求出每个点到源点的距离和每个点到终点的距离即可。
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn = 5000 + 10;
const int inf = 500000000 + 10;
struct edge
{
int to;
int cost;
};
int dis[maxn];
bool vis[maxn];
int dist[maxn];
vector<edge> G[maxn];
void spfa(int n, int start, int dis[])
{
queue<int> que;
fill(dis + 1, dis + n + 1, inf);
memset(vis, false, sizeof(vis));
dis[start] = 0;
vis[start] = true;
que.push(start);
while (!que.empty()) {
int v = que.front();
que.pop();
vis[v] = false;
for (int u = 0; u < G[v].size(); u++) {
edge e = G[v][u];
if (dis[e.to] > dis[v] + e.cost) {
dis[e.to] = dis[v] + e.cost;
if (vis[e.to] == false) {
que.push(e.to);
vis[e.to] = true;
}
}
}
}
}
int main()
{
int n, r;
scanf("%d%d", &n, &r);
while (r--) {
int a, b, d;
scanf("%d%d%d", &a, &b, &d);
edge e1 = {a, d};
edge e2 = {b, d};
G[a].push_back(e2);
G[b].push_back(e1);
}
spfa(n, 1, dis);
spfa(n, n, dist);
int mroad = dis[n];
int sec = inf;
for (int i = 1; i <= n; i++) {
for (int j = 0; j < G[i].size(); j++) {
edge e = G[i][j];
if (dis[i] + dist[e.to] + e.cost != mroad) {
sec = min(sec, dis[i] + dist[e.to] + e.cost);
}
}
}
printf("%d\n", sec);
return 0;
}