• UVA 11613 Acme Corporation(不固定流量的最小费用流)


    题意好长。。。。变量好多。。。。

    增加源点跟汇点。然后将每个月份看成一个点,然后拆成两个点u 跟 u+n。 

    从s向每个u连一条<n[u], m[i]>的弧,表示最多生产量及价值。

    从每个u+n向t连一条<s[i], -p[i]>的弧,表示最多销量及价值。

    对于存放的情况 for(int j=0; j<=e[u] ; j++) if(u + j <= M) ,由u向u+j+M连一条<INF, I*j>的弧,表示存放所要花费的价值。

    这题并不需要满足销量最大,也就是不固定流量的最小费用流,也就是说当s-t增广长度大于0的时候停止增广就行了。还有,稠密图ZKW效率不是太高。。。。

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define REP(i, n) for(int i=0; i<n; i++)
    #define CLR(a, b) memset(a, b, sizeof(a))
    #define FF(i, a, b) for(int i=a; i<b; i++)
    #define LL long long
    using namespace std;
    
    const int maxn = 300;
    const int maxe = maxn*maxn/2;
    const int INF = 1e9;
    
    struct ZKW_flow
    {
        int st, ed, ecnt, n;
        int head[maxn], dis[maxn];
        int cap[maxe], cost[maxe], to[maxe], next[maxe];
    
        void init()
        {
            CLR(head, 0);
            ecnt = 2;
        }
    
        void AddEdge(int u, int v, int cc, int ww)
        {
            cap[ecnt] = cc; cost[ecnt] = ww; to[ecnt] = v;
            next[ecnt] = head[u]; head[u] = ecnt++;
            cap[ecnt] = 0; cost[ecnt] = -ww; to[ecnt] = u;
            next[ecnt] = head[v]; head[v] = ecnt++;
        }
    
        void spfa()
        {
            REP(i, n+1) dis[i] = INF;
            priority_queue<pair<int, int> > q;
            dis[st] = 0;
            q.push(make_pair(0, st));
            while(!q.empty())
            {
                int u = q.top().second, d = -q.top().first;
                q.pop();
                if(dis[u] != d) continue;
                for(int p=head[u]; p; p=next[p])
                {
                    int& v = to[p];
                    if(cap[p] && dis[v] > d+cost[p])
                    {
                        dis[v] = d + cost[p];
                        q.push(make_pair(-dis[v], v));
                    }
                }
            }
            REP(i, n+1) dis[i] = dis[ed] - dis[i];
        }
        LL Mincost, Maxflow;
        bool use[maxn];
    
        int add_flow(int u, int flow)
        {
            if(u == ed)
            {
                if(dis[st] > 0) return flow;//不固定流量的最小费用流
                Maxflow += flow;
                Mincost += (LL)dis[st] * (LL)flow;
                return flow;
            }
            use[u] = true;
            int now = flow;
            for(int p=head[u]; p; p=next[p])
            {
                int& v = to[p];
                if(cap[p] && !use[v] && dis[u] == dis[v] + cost[p])
                {
                    int tmp = add_flow(v, min(now, cap[p]));
                    cap[p] -= tmp;
                    cap[p^1] += tmp;
                    now -= tmp;
                    if(!now) break;
                }
            }
            return flow - now;
        }
    
        bool modify_lable()
        {
            int d = INF;
            REP(u, n+1) if(use[u])
                for(int p=head[u]; p; p=next[p])
                {
                    int& v = to[p];
                    if(cap[p] && !use[v])
                        d = min(d, dis[v] + cost[p] - dis[u]);
                }
            if(d == INF) return false;
            REP(i, n+1) if(use[i]) dis[i] += d;
            return true;
        }
    
        LL MCMF(int ss, int tt, int nn)
        {
            st = ss; ed = tt; n = nn;
            Mincost = Maxflow = 0;
            spfa();
            while(true)
            {
                while(true)
                {
                    CLR(use, 0);
                    if(!add_flow(st, INF)) break;
                }
                if(!modify_lable()) break;
            }
            return Mincost;
        }
    }solver;
    
    int T, M, I, st, ed;
    int m[maxn], n[maxn], p[maxn], s[maxn], e[maxn];
    
    int main()
    {
        scanf("%d", &T);
        FF(kase, 1, T+1)
        {
            scanf("%d%d", &M, &I);
            solver.init();
            st = 0, ed = M * 2 + 1;
            FF(i, 1, M+1) scanf("%d%d%d%d%d", &m[i], &n[i], &p[i], &s[i], &e[i]);
    
            FF(i, 1, M+1)
            {
                solver.AddEdge(st, i, n[i], m[i]);
                solver.AddEdge(i+M, ed, s[i], -p[i]);
                REP(j, e[i]+1) if(i + j <= M)
                    solver.AddEdge(i, i+j+M, n[i], I*j);
                else break;
            }
    
            printf("Case %d: %lld
    ", kase, -solver.MCMF(st, ed, ed));
        }
        return 0;
    }
    


  • 相关阅读:
    Pwn-level0
    Pwn-level2
    【php】php从多个数组中取出最大的值
    【算法】php计算数字k在一段数字范围出现的次数
    【算法】php计算出丑数
    【php】php常用函数代码封装(一)数组篇
    【Golang】go语言设计模式
    什么是RPC
    【php】 php获取文件路径中的文件名和文件后缀方法
    【php】php目录路径函数系列
  • 原文地址:https://www.cnblogs.com/pangblog/p/3424174.html
Copyright © 2020-2023  润新知