zoukankan      html  css  js  c++  java
  • CCPC 2018 秦皇岛 A题 Build(网络流、限制花费的最小费用最大流)

    CCPC 2018 秦皇岛 A题 Build(网络流、限制花费的最小费用最大流)

    题意:给一个无向图,给出每条边的容量和单位花费,求从1到n费用不超过f的最大流

    如果当次spfa跑出来的流量已经不能全部买到了,那就切一部分买到的。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int maxn = 2100;
    const int maxm = 2100000;
    const int inf = 0x3f3f3f3f3f3f3f3f;
    typedef long long ll;
    struct Edge {
        int to, nex;
        ll cap, flow, cost;
    } edge[maxm];
    
    
    int head[maxn], tot;
    int pre[maxn];
    ll dis[maxn];
    bool vis[maxn];
    int N;
    
    void init(int n) {
        N = n;
        tot = 0;
        memset(head, -1, sizeof(head));
    }
    
    void addedge(int u, int v, int cap, int cost) {
        edge[tot].to = v;
        edge[tot].cap = cap;
        edge[tot].cost = cost;
        edge[tot].flow = 0;
        edge[tot].nex = head[u];
        head[u] = tot++;
        edge[tot].to = u;
        edge[tot].cap = 0;
        edge[tot].cost = -cost;
        edge[tot].flow = 0;
        edge[tot].nex = head[v];
        head[v] = tot++;
    }
    
    
    bool spfa(int s, int t) {
        queue<int> q;
        for (int i = 0; i <= N; i++) {
            dis[i] = inf;
            vis[i] = false;
            pre[i] = -1;
        }
    
        dis[s] = 0;
        vis[s] = true;
    
        q.push(s);
        while (!q.empty()) {
            int u = q.front();
            q.pop();
            vis[u] = false;
    
            for (int i = head[u]; i != -1; i = edge[i].nex) {
                int v = edge[i].to;
                if (edge[i].cap > edge[i].flow && dis[v] > dis[u] + edge[i].cost) {
                    dis[v] = dis[u] + edge[i].cost;
                    pre[v] = i;
                    if (!vis[v]) {
                        vis[v] = true;
                        q.push(v);
                    }
                }
            }
        }
        return pre[t] != -1;
    }
    
    int n, m;
    ll f;
    
    ll mcmf(int s, int t, ll &cost, ll flow) {
        cost = 0;
        while (spfa(s, t)) {
            ll Min = inf;
            ll cost1 = 0;
            for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to]) {
                if (Min > edge[i].cap - edge[i].flow)
                    Min = edge[i].cap - edge[i].flow;
            }
            for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to]) {
                edge[i].flow += Min;
                edge[i ^ 1].flow -= Min;
                cost1 += edge[i].cost;
            }
            ll tmp = (f - cost) / cost1;
            if (Min > tmp)
                return flow + tmp;
            cost += cost1 * Min;
            flow += Min;
        }
        return flow;
    }
    
    
    int mx[maxm], costi[maxm];
    int from[maxm], to[maxm];
    
    
    int main() {
        scanf("%d %d %lld", &n, &m, &f);
        init(2 * n + 1);
        addedge(0, 1, inf, 0);
        for (int i = 1; i <= n; i++) {
            addedge(i, i + n, inf, 0);
        }
        for (int i = 1; i <= m; i++) {
            scanf("%d %d %d %d", &from[i], &to[i], &mx[i], &costi[i]);
            addedge(from[i] + n, to[i], mx[i], costi[i]);
            addedge(to[i] + n, from[i], mx[i], costi[i]);
        }
        ll cost, flow;
        flow = mcmf(0, 2 * n, cost, 0);
        printf("%lld
    ", flow);
        return 0;
    }
    
  • 相关阅读:
    map迭代器
    线段树——校门外的树
    并查集——C
    并查集
    数论—— LCM
    【动态规划】合唱队形
    线段树——D
    线段树——E
    逆元,exgcd,欧拉定理,费马小定理
    待学知识点
  • 原文地址:https://www.cnblogs.com/albert-biu/p/11438272.html
Copyright © 2011-2022 走看看