zoukankan      html  css  js  c++  java
  • HDU 6118 度度熊的交易计划 最大费用可行流

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6118

    题意:中文题

    分析:

    最小费用最大流,首先建立源点 s ,与超级汇点 t 。因为生产一个商品需要花费 a[i] 元,且上限为 b[i] ,所以我们从 s 向这些点之间连一条容量为 b[i] ,费用为 a[i] 的边。同样的道理,出售一个商品可以赚到 c[i] 元,最多出售 d[i] 个,于是我们从这些点向 t 连一条容量为 d[i] ,费用为 -c[i] 的边。最后所有的公路也是花费,从 uv 连接一条双向边,容量为 INF ,费用为 k,然而要注意这道题并不是要求最大流,这道题要求的是可行流,这个只需要修改一下求增广的过程就可以了,最后答案就是费用流的相反数。

    #include <bits/stdc++.h>
    using namespace std;
    const int inf = 0x3FFFFFFF;
    const int maxn = 2222;
    struct node{
        int st, en, flow, cost, next;
        node(){}
        node(int st, int en, int flow, int cost, int next):st(st),en(en),flow(flow),cost(cost),next(next){}
    }E[101000];
    
    int num, p[maxn];
    void init(){
        memset(p, -1, sizeof(p));
        num = 0;
    }
    void add(int st, int en, int flow, int cost){
        E[num] = node(st, en, flow, cost, p[st]);
        p[st] = num++;
        E[num] = node(en, st, 0, -cost, p[en]);
        p[en] = num++;
    }
    int pre[maxn];
    int dis[maxn];
    bool fg[maxn];
    bool spfa(int st, int en)
    {
        for(int i=0;i<=en;i++){
            fg[i] = 0, dis[i] = inf, pre[i]=-1;
        }
        queue<int>q;
        q.push(st);
        fg[st]=1;
        dis[st]=0;
        while(!q.empty()){
            int u = q.front(); q.pop();
            fg[u]=0;
            for(int i=p[u];~i;i=E[i].next){
                int v = E[i].en;
                if(E[i].flow&&dis[v]>dis[u]+E[i].cost){
                    dis[v] = dis[u]+E[i].cost;
                    pre[v]=i;
                    if(!fg[v]){
                        fg[v]=1;
                        q.push(v);
                    }
                }
            }
        }
    //    if(dis[en] < inf) return 1;
    //    return 0;
        return dis[en]<=0;
    }
    
    int solve(int st, int en){
        int ans=0;
        while(spfa(st,en)){
            int d = inf;
            for(int i=pre[en];i+1;i=pre[E[i].st]) d = min(d, E[i].flow);
            for(int i=pre[en];i+1;i=pre[E[i].st]){
                E[i].flow -= d;
                E[i^1].flow += d;
                ans += d*E[i].cost;
            }
        }
        return ans;
    }
    int main()
    {
        int n,m;
        while (cin>>n>>m)
        {
            init();
            int s=0,t=n+1,cost;
            for (int i=1; i<=n; i++)
            {
                int a,b,c,d;
                cin>>a>>b>>c>>d;
                add(s,i,b,a);
                add(i,t,d,-c);
            }
            while (m--)
            {
                int u,v,k;
                cin>>u>>v>>k;
                add(u,v,inf,k);
                add(v,u,inf,k);
            }
            int ans = -solve(s,t);
            printf("%d
    ", ans);
        }
        return 0;
    }
    
  • 相关阅读:
    函数式编程(三元运算、文件操作、函数、装饰器)
    开发基础(练习题)
    开发基础(字符串操作、元祖、元组、Hash、字典、集合、字符编码转换)
    开发基础(字符编码、列表操作)
    开发基础 (变量、数据类型、格式化输出、运算符、流程控制、while循环)
    [LeetCode] 127. 单词接龙
    [LeetCode] 126. 单词接龙 II
    [LeetCode] 122. 买卖股票的最佳时机 II
    [LeetCode] 124. 二叉树中的最大路径和
    [LeetCode] 125. 验证回文串
  • 原文地址:https://www.cnblogs.com/spfa/p/7375229.html
Copyright © 2011-2022 走看看