• 【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代码
  • 相关阅读:
    TCP/IP协议详解
    linux高性能服务器编程--初见
    聚合类
    类class 2
    继承
    构造函数再探
    静态成员与友元
    MySQL图形工具SQLyog破解版
    MySQL注释符号
    数据库中多对多关系的中间表的命名规则
  • 原文地址:https://www.cnblogs.com/Mr94Kevin/p/9901591.html
Copyright © 2020-2023  润新知