您的位置:首页 > 其它

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

2013-11-14 20:59 316 查看
题意好长。。。。变量好多。。。。

增加源点跟汇点。然后将每个月份看成一个点,然后拆成两个点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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: