「BJWC 2012」冻结「分层图+最短路」

题目传送门

题解

分层图是一种不错的技巧。对于这题来说,把图复制成 k + 1 k+1 k+1份,分别命名为 0 , 1 , . . . , k 0,1,...,k 0,1,...,k层。第 i i i层的含义就是已经用了 i i i次加速魔法。

读入一条边,每层连双向边,层与层之间,底层往上层连权值减半的单向边,单向意味着只能上不能下。

然后答案就是跑最短路然后取 k + 1 k+1 k+1层的 d i s ( n ) dis(n) dis(n)最小值.

#include  #include  #include  using namespace std; #define P pair #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; } 

你可能感兴趣的:(图论,-,最短路)