zoukankan      html  css  js  c++  java
  • kuangbin专题专题十一 网络流 Minimum Cost POJ

    题目链接:https://vjudge.net/problem/POJ-2516

    思路:对于每种商品跑最小费用最大流,如果所有商品和人一起建图跑,O(v^2*m)数量级太大,会超时。

    把店里的商品拆点,入和出之间是商品库存量,起到限流作用。

    源点->人对该商品的需求->库存点入->库存点出->汇点

    源点与人之间的边的流为人的需求量,人对商品之间的边的流INF。

    源点与人的边设置费用,其他边费用0.

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <queue>
    using namespace std;
    
    const int N = 60,INF = (int)1e9;
    int n,m,k,tot;
    int head[N<<2],pre[N<<2],d[N<<2],vis[N<<2];
    int p[N][N],g[N][N],c[N][N][N];
    struct node{
        int to,nxt,cap,flow,cost;
    }e[N*N];
    
    inline void add(int u,int v,int cap,int flow,int cost){
        e[tot].to = v; e[tot].cap = cap; e[tot].flow = flow;
        e[tot].cost = cost; e[tot].nxt = head[u]; head[u] = tot++;
    
        e[tot].to = u; e[tot].cap = 0; e[tot].flow = flow;
        e[tot].cost = -cost; e[tot].nxt = head[v]; head[v] = tot++;
    }
    
    void input(int& sum_need){
        sum_need = 0;
        for(int i = 1; i <= n; ++i){
            for(int j = 1; j <= k; ++j){
                scanf("%d",&p[i][j]);
                sum_need += p[i][j];
            }
        }
        for(int i = 1; i <= m; ++i){
            for(int j = 1; j <= k; ++j)
                scanf("%d",&g[i][j]);
        }
        for(int o = 1; o <= k; ++o){
            for(int i = 1; i <= n; ++i){
                for(int j = 1; j <= m; ++j)
                    scanf("%d",&c[o][i][j]);
            }
        }
    }
    
    void build_map(int o,int s,int t){
        //0源点   1~n人  n+1~n+m 库存点入,  
        //n+m+1~n+2*m库存点出  n+2*m+1汇点。
        for(int i = 1; i <= n; ++i){
            for(int j = 1; j <= m; ++j){
                add(i,j+n,INF,0,c[o][i][j]);
            }
        }
        for(int i = 1; i <= n; ++i){
            add(s,i,p[i][o],0,0);
        }
        for(int i = 1; i <= m; ++i){
            add(i+n,i+n+m,g[i][o],0,0);
            add(i+n+m,t,INF,0,0);
        }
    }
    
    bool spfa(int s,int t){
        for(int i = s; i <= t; ++i){
            d[i] = INF; pre[i] = -1; vis[i] = false;
        }
        queue<int > que;
        que.push(s); d[s] = 0; vis[s] = true;
        while(!que.empty()){
            int now = que.front(); que.pop();
            vis[now] = false;
            for(int o = head[now]; ~o; o = e[o].nxt){
                int to = e[o].to;
                if(e[o].cap > e[o].flow && d[to] > d[now] + e[o].cost){
                    d[to] = d[now] + e[o].cost;
                    pre[to] = o;
                    if(!vis[to]){
                        vis[to] = true;
                        que.push(to);
                    }
                }
            }
        }
        if(pre[t] == -1) return false;
        else return true;
    }
    
    int mcmf(int s,int t,int& mf){
    
        int Min = INF,mc = 0;
        while(spfa(s,t)){
            Min = INF;
            for(int o = pre[t]; ~o; o = pre[e[o^1].to]){
                Min = min(Min,e[o].cap - e[o].flow);
            }
            for(int o = pre[t]; ~o; o = pre[e[o^1].to]){
                e[o].flow += Min;
                e[o^1].flow -= Min;
            }
            mf += Min;
            mc += d[t]*Min;
        }
        return mc;
    }
    
    void init_main(){
        memset(p,0,sizeof(p));
        memset(g,0,sizeof(g));
        memset(c,0,sizeof(c));
    }
    
    int main(){
    
        int s,t,mc,mf,sum_need;//商品总需求量
        while(~scanf("%d%d%d",&n,&m,&k) && (n+m+k)){
            init_main();
            input(sum_need);
            s = 0; t = n + 2*m + 1;
            mc = mf = 0;
            for(int o = 1; o <= k; ++o){//第o种商品
                for(int i = s; i <= t; ++i) head[i] = -1; tot = 0;
                build_map(o,s,t);
                mc += mcmf(s,t,mf);
            }
            //if(mf == sum_need) printf("-------------%d
    ",mc);
            //else printf("--------------no
    ");
            if(mf == sum_need) printf("%d
    ",mc);
            else printf("-1
    ");
        }
    
        return 0;
    }
  • 相关阅读:
    获取一个表的,字段,类型,长度,是否主键,是否为空,注释 等信息
    单个页面Request编码方式的改变,无需改动Web.config~
    关于锚点页内链接跳转出现问题(不响应,没有反应)的解决方法(ZT)
    40种网站设计常用技巧~
    在MasterPage中检验session是否存在~
    如何避免重构带来的危险
    早该知道的7个JavaScript技巧
    30个提高Web程序执行效率的好经验
    我学编程时犯的最大两个错误
    C# 中get和set属性的作用
  • 原文地址:https://www.cnblogs.com/SSummerZzz/p/12258875.html
Copyright © 2011-2022 走看看