【BZOJ2662】冻结

题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2662


又学到新技能了!!!

分层图最短路,一开始还以为是要建k+1个图,然后跑一遍最短路,其实没那么麻烦,我们在跑最短路的过程中就可以实现分层。

和往常一样,我们要用dist[u]+w去更新dist[v],但是为了分层,我们需要用dist[l][u]来存储最短路,表示从第0层第1个结点到第i层第u个结点的最短路,然后额外用dist[l][u]+w/2去更新dist[l+1][v],当然l+1<=k,因为我们最多进行k次操作。其实想象一下,也很好理解,相当于我们在把对哪些边使用魔法进行讨论,只不过保证无论用不用魔法,对哪些边用,都是在那种情况下的最短路,所以我们还需要求出min{dist[l][n]}作为答案。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <queue>
 5 
 6 using namespace std;
 7 
 8 const int maxn = 55, maxm = 1e3 + 5, inf = 0x3f3f3f3f;
 9 
10 int head[maxn], eid;
11 
12 struct Edge {
13     int v, w, next;
14 } edge[2 * maxm];
15 
16 inline void insert(int u, int v, int w) {
17     edge[++eid].v = v;
18     edge[eid].w = w;
19     edge[eid].next = head[u];
20     head[u] = eid;
21 }
22 
23 int k, dist[maxn][maxn], vis[maxn][maxn];
24 
25 struct node {
26     int level, id, dist;
27     node(int l, int i, int d) : level(l), id(i), dist(d) {}
28     bool operator < (const node& rhs) const {
29         return dist > rhs.dist;
30     }
31 };
32 
33 priority_queue<node> q;
34 
35 inline void dijkstra() {
36     memset(dist, inf, sizeof(dist));
37     dist[0][1] = 0;
38     q.push(node(0, 1, 0));
39     while (!q.empty()) {
40         int l = q.top().level, u = q.top().id;
41         q.pop();
42         if (vis[l][u]) continue;
43         vis[l][u] = 1;
44         for (int p = head[u]; p; p = edge[p].next) {
45             int v = edge[p].v, w = edge[p].w;
46             if (dist[l][v] > dist[l][u] + w) {
47                 dist[l][v] = dist[l][u] + w;
48                 q.push(node(l, v, dist[l][v]));
49             }
50             if (l + 1 <= k && dist[l + 1][v] > dist[l][u] + w / 2) {
51                 dist[l + 1][v] = dist[l][u] + w / 2;
52                 q.push(node(l + 1, v, dist[l + 1][v]));
53             }
54         }
55     }
56 }
57 
58 int main() {
59     int n, m, ans = inf;
60     scanf("%d%d%d", &n, &m, &k);
61     for (int i = 1; i <= m; ++i) {
62         int a, b, t;
63         scanf("%d%d%d", &a, &b, &t);
64         insert(a, b, t);
65         insert(b, a, t);
66     }
67     dijkstra();
68     for (int i = 0; i <= k; ++i)
69         ans = min(ans, dist[i][n]);
70     printf("%d", ans);
71     return 0;
72 }
AC代码

猜你喜欢

转载自www.cnblogs.com/Mr94Kevin/p/9901591.html