zoukankan      html  css  js  c++  java
  • 【网络流24题】【LOJ6013】负载平衡(环形纸牌均分,最小费最大流)

    problem

    • 一个有n个数的环
    • 每次只能向相邻的数移动,移动一个数代价为1
    • 求让所有数相等的最小代价

    solution

    • 从s向每个点连容量为库存量,费用为0的边
    • 从每个点向t连容量为平均库存量,费用为0的边
    • 在相邻两个点之间连容量为inf,费用为1的边
    • 然后跑最小费用最大流即可

    codes

    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    using namespace std;
    
    const int N = 110*2+10, M = 1000+10, inf = 1<<30;
    
    //Grape
    struct Edge{
        int from, to, cap, flow, cost;
    }e[M];
    int tot=1, head[N], Next[M];
    void AddEdge(int u, int v, int w, int c){
        //正向边,初始容量w,单位费用c
        e[++tot].from = u, e[tot].to = v, e[tot].cap = w, e[tot].flow = 0, e[tot].cost = c;
        Next[tot] = head[u], head[u] = tot;
        //反向边,初始容量0,单位费用-c,与正向边成对存储
        e[++tot].from = v, e[tot].to = u, e[tot].cap = 0, e[tot].flow = 0, e[tot].cost = -c;
        Next[tot] = head[v], head[v] = tot;
    }
    
    //Cost flow
    int s, t, incf[N], pre[N];
    int dist[N], vis[N];
    bool spfa(){
        queue<int>q;
        memset(dist,0x3f,sizeof(dist));//inf
        memset(vis,0,sizeof(vis));
        q.push(s); dist[s]=0; vis[s]=1;
        incf[s] = inf; //到s为止的增广路上各边的最小的剩余容量
        while(q.size()){
            int x = q.front(); q.pop(); vis[x] = 0;
            for(int i = head[x]; i; i = Next[i]){
                if(e[i].flow==e[i].cap)continue; //剩余容量为0,不再残量网络中,不遍历
                int y = e[i].to;
                if(dist[y]>dist[x]+e[i].cost){
                    dist[y] = dist[x]+e[i].cost;
                    incf[y] = min(incf[x], e[i].cap-e[i].flow);
                    pre[y] = i;//记录前驱,用于找方案
                    if(!vis[y])vis[y]=1, q.push(y);
                }
            }
        }
        if(dist[t] == 0x3f3f3f3f)return false;//汇点不可达,已求出最大流
        return true;
    }
    int maxflow(){
        int flow = 0, cost = 0;
        while(spfa()){
            int x = t;
            while(x != s){
                int i = pre[x];
                e[i].flow += incf[t];
                e[i^1].flow -= incf[t];
                x = e[i].from;
            }
            flow += incf[t];
            cost += dist[t]*incf[t];
        }
        return cost;
    }
    
    //Timu
    int n, a[110], sum, ans;
    
    int main(){
        ios::sync_with_stdio(false);
        cin>>n; for(int i = 1; i <= n; i++)cin>>a[i],sum+=a[i];  sum/=n;
        s = 0, t = n+1;
        for(int i = 1; i <= n; i++){
            AddEdge(s,i,a[i],0);
            AddEdge(i,t,sum,0);
            AddEdge(i,i+1>n?1:i+1,inf,1);
            AddEdge(i,i-1<1?n:i-1,inf,1);
        }
        cout<<maxflow()<<'
    ';
        return 0;
    }
  • 相关阅读:
    POJ 3261 Milk Patterns (求可重叠的k次最长重复子串)
    UVaLive 5031 Graph and Queries (Treap)
    Uva 11996 Jewel Magic (Splay)
    HYSBZ
    POJ 3580 SuperMemo (Splay 区间更新、翻转、循环右移,插入,删除,查询)
    HDU 1890 Robotic Sort (Splay 区间翻转)
    【转】ACM中java的使用
    HDU 4267 A Simple Problem with Integers (树状数组)
    POJ 1195 Mobile phones (二维树状数组)
    HDU 4417 Super Mario (树状数组/线段树)
  • 原文地址:https://www.cnblogs.com/gwj1314/p/9444652.html
Copyright © 2011-2022 走看看