题意:第一行是点数N和边数R,后面是R条无向边。求从1到n的次短路长度。
思路:模板题。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <cstdlib>
#include <set>
#include <string>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 5005;
struct edge{
int v, w, nxt;
}G[200005]; // 无向边数组要开两倍
int tot, pre[maxn];
void add(int u, int v, int w) {
G[tot].v = v;
G[tot].w = w;
G[tot].nxt = pre[u];
pre[u] = tot++;
}
int dist[maxn][2], n, r;
bool vis[maxn][2];
struct node{
int v, d, flag;
node() {}
node(int v, int d, int f) : v(v), d(d), flag(f) {}
bool operator < (const node &b) const {
if (d != b.d) {
return d > b.d;
} else {
return v > b.v;
}
}
};
void dijkstra(int s) {
memset(dist, 0x3f, sizeof(dist));
memset(vis, 0, sizeof(vis));
dist[s][0] = 0;
priority_queue<node> que;
que.push(node(s, 0, 0));
while (!que.empty()) {
node p = que.top();
que.pop();
if (vis[p.v][p.flag]) {
continue;
}
vis[p.v][p.flag] = true;
for (int i = pre[p.v]; ~i; i = G[i].nxt) {
int v = G[i].v;
int w = G[i].w;
if (!vis[v][0] && p.d + w < dist[v][0]) {
if (dist[v][0] != inf) {
dist[v][1] = dist[v][0];
que.push(node(v, dist[v][1], 1));
}
dist[v][0] = p.d + w;
que.push(node(v, dist[v][0], 0));
} else if (!vis[v][1] && p.d + w < dist[v][1]) {
dist[v][1] = p.d + w;
que.push(node(v, dist[v][1], 1));
}
}
}
}
int main(){
int u, v, w;
scanf("%d%d", &n, &r);
tot = 0;
memset(pre, -1, sizeof(pre));
while (r--) {
scanf("%d%d%d", &u, &v, &w);
add(u, v, w);
add(v, u, w);
}
dijkstra(1);
printf("%d\n", dist[n][1]);
return 0;
}