AcWing 383. 觀光
阿新 • • 發佈:2022-03-18
#include <bits/stdc++.h> using namespace std; const int N = 1010; const int M = 10010; int n, m; // n個節點,m條邊 int d[N][2]; //拆點,因為每個點都要計算最短路和次短路,所以一個點看到兩個點 int cnt[N][2]; //最短路和次短路的路線個數 bool st[N][2]; //一個st拆成兩個 int S, F; //起點和終點 struct Node { int dist; //用於Dijkstra中排序的最短距離 int id; //節點號 int type; // 0:最短路,1:次短路 }; //小頂堆,結構體對比,需要過載大於號。如果a.dist>b.dist,則表示 // a>b,因為是小頂堆,所以b在前,即dist越小越靠前 bool operator>(const Node &a, const Node &b) { return a.dist > b.dist; } priority_queue<Node, vector<Node>, greater<Node>> q; //鄰接表 int idx, h[N], e[M], w[M], ne[M]; void add(int a, int b, int c) { e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++; } //迪傑斯特拉 int dijkstra() { memset(d, 0x3f, sizeof d); //初始化距離 memset(cnt, 0, sizeof cnt); //記錄最短邊個數,次短邊個數 memset(st, false, sizeof st); //沒有在佇列中 d[S][0] = 0; //起點最短路長度為0,起點次長路徑不存在,為INF cnt[S][0] = 1; //起點最短路個數為1,起點次長路徑不存在,為INF //距離,節點號,型別:相對於拆點,一分為二 q.push({d[S][0], S, 0}); while (q.size()) { auto t = q.top(); q.pop(); // u:節點號 type:型別(最短,次短) int u = t.id, type = t.type; //二維狀態描述是不是已經入過隊了 if (st[u][type]) continue; //入隊 st[u][type] = true; for (int i = h[u]; ~i; i = ne[i]) { int j = e[i]; int dist = d[u][type] + w[i]; //可以用來鬆馳的可能距離 //這裡將“比最短路長度多1的距離”定義為次短距離 //與正常含義的次短距離不同,需要注意區分,否則理解不了 //小於最短距離 if (dist < d[j][0]) { //如果最短距離可以變為次短距離 if (dist + 1 == d[j][0]) { d[j][1] = d[j][0]; //用最短距離更新次短距離 cnt[j][1] = cnt[j][0]; //最短距離數量更新次短距離數量 q.push({d[j][1], j, 1}); //次短距離入佇列 } d[j][0] = dist; //更新最短距離 cnt[j][0] = cnt[u][0]; //更新最短距離的數量 q.push({d[j][0], j, 0}); //最短距離入佇列 } //等於最短距離 else if (dist == d[j][0]) cnt[j][0] += cnt[u][0]; //最短距離數累加 //等於次短距離 else if (dist == d[j][0] + 1) { if (!cnt[j][1]) { //沒有記錄過次短距離 d[j][1] = dist; //記錄上 q.push({d[j][1], j, 1}); //次短距離入佇列 } //這裡一定要寫成type,因為type是0或者1都可能觸發該分支 cnt[j][1] += cnt[u][type]; } } } //返回終點最短距離和次短距離的和 return cnt[F][0] + cnt[F][1]; } int main() { int T; // T組測試資料 cin >> T; while (T--) { //多組測試資料,需要初始化 memset(h, -1, sizeof h); idx = 0; // n個節點,m條邊 cin >> n >> m; int a, b, c; while (m--) { cin >> a >> b >> c; add(a, b, c); } cin >> S >> F; printf("%d\n", dijkstra()); } return 0; }