[JLOI2011]飛行路線
阿新 • • 發佈:2021-08-25
題目【拆點】【分層圖】【最短路】
思路
- 拆點: 將一個狀態 拆為 k+1 個狀態
- 原來dijkstra(dist, j)
- 現在拆成k+1個狀態, 狀態變為(dist, j, cnt) cnt為當前已免費使用的次數
程式碼(dijkstra + 拆點)
#include <bits/stdc++.h> using namespace std; const int N = 10010, M = 100010; int h[N], e[M], w[M], ne[M], idx; int n, m, k; struct State{ int u, dist, cnt; bool operator<(const State& t) const { return dist > t.dist; } }; bool st[N][11]; int dist[N][11];//拆點 int S, T; void add(int a,int b, int c) { e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++; } void dijkstra() { priority_queue<State> pq; pq.push({S, 0, 0}); memset(dist, 0x3f, sizeof dist); dist[S][0] = 0; while(pq.size()) { auto t = pq.top(); pq.pop(); int u=t.u, cnt=t.cnt; if(st[u][cnt]) continue; st[u][cnt] = true; for(int i=h[u]; ~i; i=ne[i]) { int j = e[i]; //1 走w=0 if(cnt < k && dist[j][cnt+1] > dist[u][cnt]) { dist[j][cnt+1] = dist[u][cnt]; pq.push({j,dist[j][cnt+1],cnt+1}); } //2 走w=w if(dist[j][cnt] > dist[u][cnt] + w[i]) { dist[j][cnt] = dist[u][cnt] + w[i]; pq.push({j, dist[j][cnt], cnt}); } } } } int main() { memset(h, -1, sizeof h); cin>>n>>m>>k; cin>>S>>T; while(m--) { int a,b,c; scanf("%d%d%d", &a, &b, &c); add(a,b,c); add(b,a,c); } dijkstra(); int res = INT_MAX; for(int i=0; i<=k; ++i) res = min(res, dist[T][i]); cout<<res; return 0; }