AT4845 [ABC164E] Two Currencies

原题链接

  • 题意:有 (n) 个城市,它们由 (m) 条双向道路连接,保证它们能够彼此到达。第 (i) 条道路连接 (u_i,v_i) ,需要花费 (x_i) 个银币,耗费 (t_i) 秒的时间。每个城市处都有兑换银币处,第 (i) 个城市中你可以用 (1) 个金币兑换 (c_i) 个银币,可以兑换无限次,不过兑换 (1) 次需要花费 (d_i) 秒的时间。你一开始在 (1) 号城市,有 (s) 个银币和无限多的金币,求到其它城市需要耗费的最小时间。(1<=n<=50)(1<=x_i <=50)(1 <= t_i, c_i, s, d_i <= 10^9)
  • 题解:很明显建分层图,然后跑 (dij) ,显然的是,因为 (x_i) 设定过于小,所以,分层图点的数量是 (n^3) ,需要注意的是,初期接触分层图,这个是表示了两个状态,是点和在当前点一共有的钱,这两个状态要搞成一维的才方便,但是一开始是设定的是 (x imes 2500 + money + 1) 发现有重合,所以当搞到 (x imes 5000 + money + 1) 才不会重合,这个处理不能太草率。
  • 代码:
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <stack>
#include <vector>
using namespace std;
typedef long long ll;
const ll N = 1e6 + 99;
const ll NN = 2500;
ll pos(ll x, ll money) {
    return x*2 * 2500 + money + 1;
}
struct edge {
    ll v, w;
};
vector<edge>G[N];
struct Node {
    ll pos, dis;
    bool operator<(Node rhs)const {
        return rhs.dis < dis;
    }
};
priority_queue<Node>pq;
bool vis[N];
ll d[N];
void dij(ll s) {
    pq.push({s, 0});
    memset(d, 0x3f, sizeof d);
    d[s] = 0;
    while (!pq.empty()) {
        auto now = pq.top();
        pq.pop();
        ll u = now.pos;
        if (vis[u])continue;
        vis[u] = 1;
        for (auto e:G[u]) {
            if (d[e.v] > d[u] + e.w) {
                d[e.v] = d[u] + e.w;
                pq.push({e.v, d[e.v]});
            }
        }
    }
}
void add(ll u, ll v, ll w) {G[u].push_back({v, w});}
ll co[N], dd[N];
void solve() {
    ll n, m, kk;
    cin >> n >> m >> kk;
    for (ll i = 1; i <= m; i++) {
        ll u, v, c, t;
        cin >> u >> v >>c >> t;
        for (ll j = c; j <= NN; j++ ) {
            add(pos(u, j), pos(v, j - c), t);
            add(pos(v, j), pos(u, j - c), t);
        }
    }
    for (ll i = 1; i <= n; i++) {
        cin >> co[i] >> dd[i];
        for (ll j = 0; j + co[i] <= NN; j++) {
            add(pos(i, j), pos(i, j + co[i]), dd[i]);
        }
    }
    dij(pos(1, min(NN, kk)));
    for (ll i = 2; i <= n; i++) {
        ll ans = d[pos(i, 0)];
        for (ll j = 0; j <= NN; j++) {
            ans = min(d[pos(i, j)], ans);
        }
        cout << ans << endl;
    }
}
signed main() {
    ll t = 1;
    while (t--) solve();
    return 0;
}
原文地址:https://www.cnblogs.com/Xiao-yan/p/14581002.html