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\n", kase, -solver.MCMF(st, ed, ed));
    }
    return 0;
}


 

 

posted @ 2013-11-14 20:59  pangbangb  阅读(246)  评论(0编辑  收藏  举报