P4822 [BJWC2012]冻结(分层图最短路)

传送门

题目描述:

我们考虑最简单的旅行问题吧: 现在这个大陆上有 NN 个城市,MM 条双向的道路。城市编号为 11 ~ NN,我们在 11 号城市,需要到 NN 号城市,怎样才能最快地到达呢?

这不就是最短路问题吗?我们都知道可以用 Dijkstra、Bellman-Ford、Floyd-Warshall等算法来解决。

现在,我们一共有 KK 张可以使时间变慢 50%的 SpellCard,也就是说,在通过某条路径时,我们可以选择使用一张卡片,这样,我们通过这一条道路的时间 就可以减少到原先的一半。需要注意的是:

  1. 在一条道路上最多只能使用一张 SpellCard。
  2. 使用一张SpellCard 只在一条道路上起作用。
  3. 你不必使用完所有的 SpellCard。

给定以上的信息,你的任务是:求出在可以使用这不超过 KK 张时间减速的 SpellCard 之情形下,从城市 11 到城市 NN 最少需要多长时间。

思路分层图最短路

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 10000005;
const int inf = 0x3f3f3f3f;
struct edge {
    int f, t, w, nxt;
}e[maxn * 2];
int hd[maxn], tot;
void add(int f, int t, int w) {
    e[++tot] = { f,t,w,hd[f] };
    hd[f] = tot;
}
int dis[maxn];
bool vis[maxn];
struct node {
    int dis, id;
    bool operator<(node b)const {
        return dis > b.dis;
    }
};
void dj(int s) {
    memset(dis, 0x3f, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    priority_queue<node>q;
    dis[s] = 0;
    q.push({ 0,s });
    while (!q.empty()) {
        node t = q.top(); q.pop();
        if (vis[t.id])continue;
        vis[t.id] = 1;
        int u = t.id;
        for (int i = hd[u]; i; i = e[i].nxt) {
            int v = e[i].t;
            if (vis[v])continue;
            if (dis[u] + e[i].w < dis[v]) {
                dis[v] = dis[u] + e[i].w;
                q.push({ dis[v], v });
            }
        }
    }
}
int n, m, k;
int s, t;
int main() {
    //freopen("test.txt", "r", stdin);
    scanf("%d%d%d", &n, &m, &k);
    for (int i = 1; i <= m; i++) {
        int a, b, w; scanf("%d%d%d", &a, &b, &w);
        for (int j = 0; j <= k; j++) {//为每一层建图
            add(j*n+a, j*n+b, w);
            add(j*n+b, j*n+a, w);
            if (j > 0) {//两层之间连单向边
                add((j - 1) * n + a, j * n + b, w >> 1);
                add((j - 1) * n + b, j * n + a, w >> 1);
            }
        }
    }
    int ans = inf;
    dj(1);
    for (int i = 0; i <= k; i++) {//每一层到终点的最小值
        ans = min(ans, dis[i * n + n]);
    }
    printf("%d",ans);
    return 0;
}

 

posted @ 2021-04-16 19:15  cono奇犽哒  阅读(55)  评论(0)    收藏  举报