# 【CSES】1202. Investigation ## [題目連結](https://cses.fi/problemset/task/1202/) ## **時間複雜度** * $O(ElogV)$ ## **解題想法** 這題我第一次看起來覺得很複雜,但是仔細想一下之後就會發現其實沒有很難解,只是將 Dijkstra 搭配上 DP 就可以處理掉了 然後在進行 Dijkstra 的時候要同時追蹤下面四個東西 1. 最短距離:`dis[]` 2. 最短距離的解數量: `routes[]` 3. 最短距離且最少的班機數: `minf[]` 4. 最短距離且最少的班機數: `maxf[]` 對於每個節點 $v$,我們都會考慮他的所有權重為 $w$ 的鄰居 $u$,當我們可以鬆弛邊 $vu$ (dis[v] > dis[u] + w)時,就將變數的值更改成下面這樣 1. 最短距離:`dis[v]` = `dis[u] + w` 2. 最短距離的解數量: `routes[v]` = `routes[u]` 3. 最短距離且最少的班機數: `minf[v]` = `minf[u] + 1` 4. 最短距離且最少的班機數: `maxf[v]` = `maxf[v] + 1` 但跟平常的 Dijkstra 不一樣的是我們還必須考慮到 dis[v] = dis[u] + w 的情況(因為你不會知道當前是不是最段距離),所以當 dis[v] = dis[u] + w 成立時,我們將值更新成下變這樣 1. 最短距離:`dis[v]` 不更新 2. 最短距離的解數量: `routes[v]` = `( routes[v] + routes[u] ) % Mod` ➨ 這邊記得取模 3. 最短距離且最少的班機數: `minf[v]` = `min( minf[v], minf[u] + 1 )` 4. 最短距離且最少的班機數: `maxf[v]` = `max( maxf[v], maxf[u] + 1 )` ## **完整程式** ```cpp= /* Question : CSES 1202. Investigation */ #include<bits/stdc++.h> using namespace std; #define opt ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0); #define pirq(type) priority_queue<type, vector<type>, greater<type>> #define mem(x, value) memset(x, value, sizeof(x)); #define pii pair<int, int> #define pll pair<long long, long long> #define pdd pair<double, double> #define pb push_back #define f first #define s second #define int long long const auto dir = vector< pair<int, int> > { {1, 0}, {0, 1}, {-1, 0}, {0, -1} }; const int MAXN = 1e5 + 50; const int Mod = 1e9 + 7; int n, m, u, v, w, dis[MAXN]; vector<vector<pii>> graph; struct Node{ int maxf = 0, minf = 0, routes = 0; } dp[MAXN]; void dij( int root ){ pirq(pii) pq; pq.push({0, root}); dis[root] = 0; dp[root].routes = 1; while( !pq.empty() ){ int d = pq.top().f; int node = pq.top().s; pq.pop(); if( d > dis[node] ) continue; for( auto i : graph[node] ){ int v = i.f; int w = i.s; // Weight if( d + w == dis[v] ){ dp[v].routes = ( dp[v].routes + dp[node].routes ) % Mod; dp[v].maxf = max( dp[v].maxf, dp[node].maxf + 1); dp[v].minf = min( dp[v].minf, dp[node].minf + 1); }else if( d + w < dis[v] ){ dis[v] = d + w; dp[v].routes = dp[node].routes; dp[v].maxf = dp[node].maxf + 1; dp[v].minf = dp[node].minf + 1; pq.push({dis[v], v}); } } } } signed main(){ opt; cin >> n >> m; graph.resize(n+5); for( int i = 0 ; i < m ; i++ ){ cin >> u >> v >> w; graph[u].pb({v, w}); } mem(dis, 0x3F); dij(1); cout << dis[n] << " " << dp[n].routes << " " << dp[n].minf << " " << dp[n].maxf << "\n"; } ```