QOJ.ac

QOJ

Type: Editorial

Status: Open

Posted by: wsy_I

Posted at:

Last updated:

Back to Problem

严肃复习分层图

图论专题的第一题。其实很分层图模板。

建立分层图,$(u,h)$ 这个点表示到达点 $u$ 疲劳值为 $h$ 时候的最短距离。那么最短路的时候就可以分类讨论两种转移了。

不需要显式建立分层图,具体转移方法如下: - 假如 $h_u>h_v$ 的话,就相当于这些边 $\forall 0\leq i\leq H,(u,i)\to (v,0)$ 这么做。 - 否则相当于 $(u,i)\to (v,i+h_v-h_u)$ 这些边这么做。

具体的做法,跟 dijkstra 模板一样,假如计算得到的距离更小,那么就更新距离,并且把这个点塞到优先队列中。

时间复杂度 $O(nH\log (nH))$,空间复杂度 $O(nH)$。

#include <bits/stdc++.h>
#define rep(i, l, r) for(int i = (l); i <= (r); i ++ )
#define per(i, l, r) for(int i = (l); i >= (r); i -- )
#define frein(s) freopen(s, "r", stdin)
#define freout(s) freopen(s, "w", stdout)
#define int long long
#define endl '\n'
using namespace std;

constexpr int N = 1e4 + 5;
constexpr int H = 100 + 5;
constexpr int INF = 0x3f3f3f3f3f3f3f3f;
int n, m, dis[N][H], mh, h[N];
bool vis[N][H];
vector<pair<int, int> > g[N];
struct Node {
    int u, h, dis;
    Node(int _u = 0, int _h = 0, int _dis = 0) : u(_u), h(_h), dis(_dis) {}
    bool operator > (const Node &t) const {
        return dis > t.dis;
    }
};
priority_queue<Node, vector<Node>, greater<Node> > q;

void dijkstra() {
    memset(dis, 0x3f, sizeof dis);
    memset(vis, false, sizeof vis);
    q.push(Node(1, 0, 0));
    dis[1][0] = 0;
    while(!q.empty()) {
        Node u = q.top();
        q.pop();
        if(vis[u.u][u.h]) continue;
        vis[u.u][u.h] = true;
        for(auto p : g[u.u]) {
            int v = p.first, w = p.second;
            if(h[v] < h[u.u]) {
                rep(i, 0, mh) {
                    if(dis[v][0] > dis[u.u][i] + w) {
                        dis[v][0] = dis[u.u][i] + w;
                        q.push(Node(v, 0, dis[v][0]));
                    }
                }
            } else {
                rep(i, 0, mh - h[v] + h[u.u]) {
                    int nh = i + h[v] - h[u.u];
                    if(dis[v][nh] > dis[u.u][i] + w) {
                        dis[v][nh] = dis[u.u][i] + w;
                        q.push(Node(v, nh, dis[v][nh]));
                    }
                }
            }
        }
    }
}

signed main() {
    frein("trail.in"), freout("trail.out");
    ios :: sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    cin >> n >> m >> mh;
    rep(i, 1, n) cin >> h[i];
    rep(i, 1, m) {
        int u, v, w;
        cin >> u >> v >> w;
        g[u].emplace_back(v, w);
        g[v].emplace_back(u, w);
    }
    dijkstra();
    rep(i, 2, n) {
        int res = INF;
        rep(j, 0, mh) res = min(res, dis[i][j]);
        cout << (res == INF ? -1 : res) << " ";
    }
    return 0; 
}

Comments

No comments yet.