「BJWC 2012」凍結「分層圖+最短路」
阿新 • • 發佈:2018-11-11
題解
分層圖是一種不錯的技巧。對於這題來說,把圖複製成 份,分別命名為 層。第 層的含義就是已經用了 次加速魔法。
讀入一條邊,每層連雙向邊,層與層之間,底層往上層連權值減半的單向邊,單向意味著只能上不能下。
然後答案就是跑最短路然後取 層的 最小值.
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
#define P pair<int, int>
#define px first
#define py second
const int N = 5010;
int n, m, k;
int dis[N];
vector<P> G[N];
int Dijkstra() {
priority_queue<P, vector<P>, greater<P> > Q;
Q.push(P(dis[1] = 0, 1));
for(int i = 2; i <= 5000; i ++) dis[i] = 1 << 29;
for(; Q.size(); ) {
P k = Q.top(); Q.pop(); int u = k.py;
if(dis[u] < k.px) continue ;
for(int i = 0; i < G[u].size(); i ++) {
int v = G[u][i].px, w = G[u][i].py;
if(dis[v] > dis[u] + w) {
Q.push(P(dis[v] = dis[u] + w, v));
}
}
}
int ans = dis[n], base = n;
for(int i = 1; i <= k; i ++, base += n)
if(ans > dis[base + n]) ans = dis[base + n];
return ans;
}
int main() {
scanf("%d%d%d", &n, &m, &k);
for(int i = 1, u, v, w; i <= m; i ++) {
scanf("%d%d%d", &u, &v, &w);
int base = 0;
for(int j = 1; j <= k + 1; j ++, base += n) {
G[base + u].push_back(P(base + v, w));
G[base + v].push_back(P(base + u, w));
if(base) {
G[base - n + u].push_back(P(base + v, w >> 1));
G[base - n + v].push_back(P(base + u, w >> 1));
}
}
}
printf("%d\n", Dijkstra());
return 0;
}