P1251 网络流做法 30分
  • 板块灌水区
  • 楼主cancan123456
  • 当前回复1
  • 已保存回复1
  • 发布时间2021/8/7 11:01
  • 上次更新2023/11/4 11:44:50
查看原帖
P1251 网络流做法 30分
448887
cancan123456楼主2021/8/7 11:01
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
#define maxn 2005
#define INF 9223372036854775807LL
typedef long long ll;
struct Edge {
    ll v, flow, cost, next;
};
ll N;
ll r[maxn];
ll p, m, f, n, s;
void input() {
    scanf("%lld", &N);
    for (ll i = 1; i <= N; i++) {
        scanf("%lld", r + i);
    }
    scanf("%lld %lld %lld %lld %lld", &p, &m, &f, &n, &s);
}
struct Graph {
    Edge edge[(6 * maxn) * 2];
    ll head[2 * maxn];
    ll cnt = 1;
    void __add_edge(ll u, ll v, ll flow, ll cost) {
        cnt++;
        edge[cnt].v = v;
        edge[cnt].flow = flow;
        edge[cnt].cost = cost;
        edge[cnt].next = head[u];
        head[u] = cnt;
    }
    void add_edge(ll u, ll v, ll flow, ll cost) {
        __add_edge(u, v, flow,  cost);
        __add_edge(v, u,    0, -cost);
    }
    ll s, t;
    ll min(ll a, ll b) {
        return a < b ? a : b;
    }
    ll max_flow = 0, min_cost = 0;
    // 经过的总流量 
    ll flow_[2 * maxn];
    // 经过的总价格 
    ll cost_[2 * maxn];
    // 记录路径
    ll pre[2 * maxn];
    ll last[2 * maxn];
    bool inq[2 * maxn];
    bool spfa() {
        memset(cost_, 0x3f, sizeof(cost_));
        cost_[s] = 0;
        queue < ll > q;
        q.push(s);
        memset(inq, false, sizeof(inq));
        inq[s] = true;
        memset(flow_, 0, sizeof(flow_));
        flow_[s] = INF;
        while (!q.empty()) {
            ll u = q.front(); q.pop();
            inq[u] = false;
            for (ll i = head[u]; i; i = edge[i].next) {
                ll v = edge[i].v, f = edge[i].flow, c = edge[i].cost;
                if (f > 0 && cost_[v] > cost_[u] + c) {
                    cost_[v] = cost_[u] + c;
                    flow_[v] = min(flow_[u], f);
                    pre[v] = u;
                    last[v] = i;
                    if (!inq[v]) {
                        q.push(v);
                        inq[v] = true;
                    }
                }
            }
        }
        return cost_[t] != 0x3f3f3f3f3f3f3f3f;
    }
    void mcmf() {
        while (spfa()) {
            max_flow += flow_[t];
            min_cost += flow_[t] * cost_[t];
            ll now = t;
            while (now != s) {
                edge[last[now]].flow -= flow_[t];
                edge[last[now] ^ 1].flow += flow_[t];
                now = pre[now];
            }
        }
    }
    void init() {
        s = 0;
        t = 2 * N + 1;
        // 每天晚上获得脏毛巾 
        for (ll i = 1; i <= N; i++) {
            add_edge(s, i + N, r[i], 0);
        }
        // 每天早上取出干净的毛巾 
        for (ll i = 1; i <= N; i++) {
            add_edge(i, t, r[i], 0);
        }
        // 每天晚上到下一天晚上 
        for (ll i = 1; i < N; i++) {
            add_edge(i + N, i + N + 1, INF, 0);
        }
        // 送到快洗部 
        for (ll i = 1; i <= N - m; i++) {
            add_edge(i + N, i + m, INF, f);
        }
        // 送到慢洗部 
        for (ll i = 1; i <= N - n; i++) {
            add_edge(i + N, i + n, INF, s);
        }
        // 购买毛巾 
        for (ll i = 1; i <= N; i++) {
            add_edge(s, i, INF, p);
        }
    }
} g;
signed main() {
    input();
    g.init();
    g.mcmf();
    printf("%lld", g.min_cost);
    return 0;
}

样例过了

提交 30 分

2021/8/7 11:01
加载中...