luogu 2865 [USACO06NOV]路障Roadblocks (次短路 堆優化Dijkstra)
題目描述
Bessie has moved to a small farm and sometimes enjoys returning to visit one of her best friends. She does not want to get to her old home too quickly, because she likes the scenery along the way. She has decided to take the second-shortest rather than the shortest path. She knows there must be some second-shortest path.
The countryside consists of R (1 ≤ R ≤ 100,000) bidirectional roads, each linking two of the N (1 ≤ N ≤ 5000) intersections, conveniently numbered 1..N. Bessie starts at intersection 1, and her friend (the destination) is at intersection N.
The second-shortest path may share roads with any of the shortest paths, and it may backtrack i.e., use the same road or intersection more than once. The second-shortest path is the shortest path whose length is longer than the shortest path(s) (i.e., if two or more shortest paths exist, the second-shortest path is the one whose length is longer than those but no longer than any other path).
貝茜把家搬到了一個小農場,但她常常回到FJ的農場去拜訪她的朋友。貝茜很喜歡路邊的風景,不想那麼快地結束她的旅途,於是她每次回農場,都會選擇第二短的路徑,而不象我們所習慣的那樣,選擇最短路。 貝茜所在的鄉村有R(1<=R<=100,000)條雙向道路,每條路都聯結了所有的N(1<=N<=5000)個農場中的某兩個。貝茜居住在農場1,她的朋友們居住在農場N(即貝茜每次旅行的目的地)。 貝茜選擇的第二短的路徑中,可以包含任何一條在最短路中出現的道路,並且,一條路可以重複走多次。當然咯,第二短路的長度必須嚴格大於最短路(可能有多條)的長度,但它的長度必須不大於所有除最短路外的路徑的長度。
輸入輸出格式
輸入格式:
Line 1: Two space-separated integers: N and R
Lines 2..R+1: Each line contains three space-separated integers: A, B, and D that describe a road that connects intersections A and B and has length D (1 ≤ D ≤ 5000)
輸出格式:
Line 1: The length of the second shortest path between node 1 and node N
輸入輸出樣例
輸入樣例#1:
4 4
1 2 100
2 4 200
2 3 250
3 4 100
輸出樣例#1:
450
說明
Two routes: 1 -> 2 -> 4 (length 100+200=300) and 1 -> 2 -> 3 -> 4 (length 100+250+100=450)
題目連結:https://www.luogu.org/problemnew/show/P2865
題目分析:由於同一個邊可以走多次,故去掉vis陣列的限制,求最短路的過程中同時記錄最短路和次短路,注意更新時的條件,還要注意的是起點的次短路不是0!
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
int const INF = 0x3fffffff;
int const MAXN = 5005;
int const MAXM = 1e5 + 5;
int n, m, dis[MAXN][2];
int cnt, head[MAXN];
struct EDGE {
int to, w, nxt;
}e[MAXM << 1];
priority_queue< pair<int, int>, vector< pair<int, int> >, greater< pair<int, int> > > q;
void Init() {
cnt = 0;
memset(head, -1, sizeof(head));
}
void Add(int u, int v, int w) {
e[cnt].to = v;
e[cnt].w = w;
e[cnt].nxt = head[u];
head[u] = cnt++;
}
void SlackPath(int v, int newDis) {
if (dis[v][0] > newDis) {
dis[v][1] = dis[v][0];
dis[v][0] = newDis;
q.push(make_pair(newDis, v));
} else if (dis[v][0] < newDis && newDis < dis[v][1]) {
dis[v][1] = newDis;
q.push(make_pair(newDis, v));
}
}
void HeapDijkstra(int v0) {
for (int i = 1; i <= n; i++) {
dis[i][0] = INF;
dis[i][1] = INF;
}
dis[v0][0] = 0;
q.push(make_pair(0, v0));
while (!q.empty()) {
int u = q.top().second;
q.pop();
for (int i = head[u]; i != -1; i = e[i].nxt) {
int v = e[i].to;
SlackPath(v, dis[u][0] + e[i].w);
SlackPath(v, dis[u][1] + e[i].w);
// printf("dis[%d][0] = %d dis[%d][1] = %d\n", v, dis[v][0], v, dis[v][1]);
}
}
}
int main() {
Init();
int u, v, w;
scanf("%d %d", &n, &m);
for (int i = 0; i < m; i++) {
scanf("%d %d %d", &u, &v, &w);
Add(u, v, w);
Add(v, u, w);
}
HeapDijkstra(1);
printf("%d\n", dis[n][1]);
}