zoukankan      html  css  js  c++  java
  • bzoj 1449 费用流

    思路:先把没有进行的场次规定双方都为负,对于x胜y负 变为x + 1胜 y - 1 负所需要的代价为 2 * C[ i ] * x  - 2 * D[ i ] * y + C[ i ] + D[ i ],

    我们根据这个拆边建图,对于a和b进行的一场w, w流出的流量为1,并指向a 和 b,然后跑费用流。

    #include<bits/stdc++.h>
    #define LL long long
    #define fi first
    #define se second
    #define mk make_pair
    #define PII pair<int, int>
    #define y1 skldjfskldjg
    #define y2 skldfjsklejg
    
    using namespace std;
    
    const int N = 6000 + 7;
    const int M = 2e5 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9 +7;
    
    int n, m, win[N], lose[N], C[N], D[N], ans[N], cnt[N], S, T;
    int head[N], pre[N], dist[N], edgenum;
    bool vis[N];
    PII a[N];
    
    struct Edge {
        int from, to, cap, flow, cost, next;
    } edge[M];
    
    void init() {
        edgenum = 0;
        memset(head, -1, sizeof(head));
    }
    
    void addEdge(int u, int v, int w, int c) {
        Edge E1 = {u, v, w, 0, c, head[u]};
        edge[edgenum] = E1;
        head[u] = edgenum++;
        Edge E2 = {v, u, 0, 0, -c, head[v]};
        edge[edgenum] = E2;
        head[v] = edgenum++;
    }
    
    bool SPFA(int s, int t) {
        queue<int> Q;
        memset(dist, INF, sizeof(dist));
        memset(vis, false, sizeof(vis));
        memset(pre, -1, sizeof(pre));
        dist[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].next) {
                Edge E = edge[i];
                if(dist[E.to] > dist[u] + E.cost && E.cap > E.flow) {
                    dist[E.to] = dist[u] + E.cost;
                    pre[E.to] = i;
                    if(!vis[E.to]) {
                        vis[E.to] = true;
                        Q.push(E.to);
                    }
                }
            }
        }
        return pre[t] != -1;
    }
    
    void MCMF(int s, int t, LL &cost, int &flow) {
        flow = 0; cost = 0;
        while(SPFA(s, t)) {
            int Min = INF;
            for(int i = pre[t]; i != -1; i = pre[edge[i^1].to]) {
                Edge E = edge[i];
                Min = min(Min, E.cap - E.flow);
            }
            for(int i = pre[t]; i != -1; i = pre[edge[i^1].to]) {
                edge[i].flow += Min;
                edge[i^1].flow -= Min;
                cost += edge[i].cost * Min;
            }
            flow += Min;
        }
    }
    
    int main() {
        init();
        scanf("%d%d", &n, &m);
        S = 0, T = n + m + 1;
        for(int i = 1; i <= n; i++) {
            scanf("%d%d%d%d", &win[i], &lose[i], &C[i], &D[i]);
            cnt[i] = win[i] + lose[i];
        }
    
        for(int i = 1; i <= m; i++) {
            scanf("%d%d", &a[i].fi, &a[i].se);
            addEdge(S, i, 1, 0);
            addEdge(i, m + a[i].fi, 1, 0);
            addEdge(i, m + a[i].se, 1, 0);
            cnt[a[i].fi]++; cnt[a[i].se]++;
        }
    
        LL ans = 0;
        for(int i = 1; i <= n; i++) {
            ans += 1ll * C[i] * win[i] * win[i] + 1ll * D[i] * (cnt[i] - win[i]) * (cnt[i] - win[i]);
        }
        for(int i = 1; i <= n; i++) {
            int num = cnt[i] - lose[i] - win[i];
            int x = win[i], y = cnt[i] - win[i];
    
            while(num--) {
                addEdge(m + i, T, 1, 2 * C[i] * x - 2 * D[i] * y + C[i] + D[i]);
                x++; y--;
            }
        }
    
        LL cost; int flow;
        MCMF(S, T, cost, flow);
        printf("%lld
    ", ans + cost);
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    SQL 实现月度留存率/复购率
    Mac安装mysql数据库,并用navicat链接
    MAC电脑安装git
    form 表格提交
    幼稚从来都是相对的
    Vue 80端口无法使用,直接运行到1024问题
    iOS SDK framework 真机和模拟器合并步骤
    XCODE调试
    UN: Half of Refugee Children Do Not Go to School
    Vue界面传值逻辑
  • 原文地址:https://www.cnblogs.com/CJLHY/p/9456303.html
Copyright © 2011-2022 走看看