您的位置:首页 > 其它

POJ2516 Minimum Cost

2016-04-30 17:04 387 查看
一.原题链接:http://poj.org/problem?id=2516

二.题目大意:Dearboy是销售商,有N个店主帮他卖东西,他有M个生产地,有K种商品,每个生产地的每种商品给每个店主的花费都是不同的,求在满足所有店主的预定下,(不满足输出-1),求最小花费。

三.思路:明显的最小费用最大流问题,真的很明显。刚开始还想把K个商品拆了中间连一条其花费的线,听说会超时,建议不要试。其实可以每种商品求一次最大流,如果其中一种商品不满足店主需求,输出-1,全部满足直接把它们都加起来。

建图如下:(求K次)

1.超级源点S和每个生产地连起来,容量为其产出,花费为0。

2.超级汇点T和每个店主连起来,容量为其需求,花费为0。(每次都需要满流,不然输出-1)

3.生产地和店主之间连对应的花费。

注意事项:

1.它给的是单位容量的花费,所以记得要乘上容量啊,就是说在求花费的时候,在索引路的时候,要顺手把增广的流乘以单位花费啊,就是在这里WA了一次。画图画一边就知道是自己傻逼了。

2.我为什么要使用堆空间呢,因为我想在一个函数里面建图,这样每求一次最大流后它就会自动析构,使用栈空间又怕爆,所以。。

四.代码:

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <cstdlib>

using namespace std;

const int INF = 0x3f3f3f3f,
MAX_SIZE = 1000;

class AdjList
{
public:
int *head, cnt;
struct Edge
{
int cost, cap, v, next;
}*edges;

AdjList()
{
edges = new Edge[MAX_SIZE*MAX_SIZE];
head = new int[MAX_SIZE];
cnt = 0;
memset(head, -1, sizeof(int)*MAX_SIZE);
}

~AdjList()
{
delete[] edges;
delete[] head;
}
void addEdge(int u, int v, int cap, int cost)
{
edges[cnt].v = v, edges[cnt].cap = cap,
edges[cnt].cost = cost, edges[cnt].next = head[u];
head[u] = cnt++;

edges[cnt].v = u, edges[cnt].cap = 0,
edges[cnt].cost = -cost, edges[cnt].next = head[v];
head[v] = cnt++;
}
};

class MinCost
{
public:
AdjList G;
int *dist, *pre, *path, s, t;
MinCost()
{
dist = new int[MAX_SIZE];
pre = new int[MAX_SIZE];
path = new int[MAX_SIZE];
}

~MinCost()
{
delete[] dist;
delete[] pre;
delete[] path;
}

bool SPFA()
{
bool inQue[MAX_SIZE];
queue <int> que;
int cur, v, i;

memset(dist, INF, sizeof(int)*MAX_SIZE);
memset(inQue, 0, sizeof(inQue));
memset(pre, -1, sizeof(int)*MAX_SIZE);

dist[s] = 0;
que.push(s);
inQue[s] = true;

while(!que.empty()){
cur = que.front();
que.pop();
inQue[cur] = false;
for(i = G.head[cur]; i != -1; i = G.edges[i].next){
v = G.edges[i].v;
if(G.edges[i].cap && dist[v] > dist[cur] + G.edges[i].cost){
dist[v] = dist[cur] + G.edges[i].cost;
pre[v] = cur;
path[v] = i;
if(!inQue[v]){
que.push(v);
inQue[v] = true;
}
}
}
}
return pre[t] != -1;
}

int ford_fulkerson(int &maxFlow)
{
int sum = 0, u, v, minFlow, i;
maxFlow = 0;
while(SPFA()){
minFlow = INF;
for(u = pre[t], v = t; u != -1; v = u, u = pre[u]){
i = path[v];
minFlow = min(minFlow, G.edges[i].cap);
}

maxFlow += minFlow;
for(u = pre[t], v = t; u != -1; v = u, u = pre[u]){
i = path[v];
G.edges[i].cap -= minFlow;
G.edges[i^1].cap += minFlow;
sum += minFlow*G.edges[i].cost;
}
}
return sum;
}
};

const int MAX_N = 58;
int N, M, K,
orders[MAX_N][MAX_N],
supply[MAX_N][MAX_N],
cost[MAX_N][MAX_N][MAX_N];

int getMinCost(int foodId)
{
MinCost poj2516;
int i, j, s, t, maxFlow, sumOrder, res;

s = M+N+1, t = M+N+2;
poj2516.s = s, poj2516.t = t;
sumOrder = 0;

for(i = 1; i <= M; i++)
poj2516.G.addEdge(s, i, supply[i][foodId], 0);

for(i = 1; i <= N; i++){
poj2516.G.addEdge(i + M, t, orders[i][foodId], 0);
sumOrder += orders[i][foodId];
}

for(i = 1; i <= M; i++)
for(j = 1;
aabf
j <= N; j++)
poj2516.G.addEdge(i, j+M, INF, cost[foodId][j][i]);

res = poj2516.ford_fulkerson(maxFlow);
if(sumOrder != maxFlow)
return -1;
else
return res;
}

int main()
{
//freopen("in.txt", "r", stdin);

int i, j, t, temp, sum;
while(~scanf("%d%d%d", &N, &M, &K) && (N+M+K)){

for(i = 1; i <= N; i++)
for(j = 1; j <= K; j++)
scanf("%d", &orders[i][j]);

for(i = 1; i <= M; i++)
for(j = 1; j <= K; j++)
scanf("%d", &supply[i][j]);

for(t = 1; t <= K; t++)
for(i = 1; i <= N; i++)
for(j = 1; j <= M; j++)
scanf("%d", &cost[t][i][j]);

sum = 0;
for(t = 1; t <= K; t++){
temp = getMinCost(t);
if(temp != -1)
sum += temp;
else{
sum = -1;
break;
}
}

printf("%d\n", sum);
}

return 0;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: