POJ 2516 Minimum Cost 费用流

就是说有N个商人,和M个货源,然后一共是K种商品

输入第一行是N M K

接下来是N行,每行K个,表示商人对各种商品的需求情况,需求数都在[0,3]内

再接下来是M行,每行K个,表示货源中每种商品的供应情况,供应书也在[0,3]内

再接下来是K个N*M的矩阵,第x个矩阵的第y行第z列表示第x种商品从第z个货源运输到第y个商人那里需要多少花费(1个的花费)

然后问你现在想完成从货源到商人的运输,问商人们能否得到他们想要的那么多的货物,不能就输出-1,能就输出最小总花费


嗯,第一次写费用流,费好大力气读懂题之后,感觉像二分图啊,从货源到商人,但是边太多了,二分图没法做啊,不过其实图也类似于一个二分图,但是还是当普通图来对待,跑费用流,

然后,货物好多啊,怎么办,连重边的话,怎么区分呢?后来看网上的说法是对每种商品都跑一次费用流,不知道整体上一次跑的话该怎么跑

好,然后对于每种商品,先建一个超级源点,连接每个货源,容量就是这个货源的商品数,花费呢,就是0,先把货源商品数给约束了,然后建个超级汇点,连接每个商人,容量,就是商人的所需商品数,保证最后得到的商品数不会超过所以商人的所需数量,然后中间货源到商人建边,容量就为无穷,因为在超级源点和超级汇点那里已经约束了,费用就是对应的费用

呃,当然,还有判断能否提供商人所需的数量,可以在跑费用流时跑出来,但其实可以提前算出来,因为每个货源都可以给所有商人供货,所以如果货源的总商品数<商人的总需求数,肯定就是不可以,直接就是-1即可,否则就肯定能满足

然后跑k次费用流,算出答案即可


#include <string>
#include <iostream>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <vector>
#include <fstream>
#include <queue>
using namespace std;
#define ll long long
#define INF 0x3f3f3f3f
#define maxn 10005
#define maxm 100005
//最小费用最大流,求最大费用只需要取相反数,结果取相反数即可。
//点的总数为 N,点的编号[0,N-1]
struct Edge
{
	int to, next, cap, flow, cost;
}edge[maxm];
int head[maxn], tol;
int pre[maxn], dist[maxn];
bool vis[maxn];
int N;//节点总个数,节点编号从0~N-1
void init(int n)
{
	N = n;
	tol = 0;
	memset(head, -1, sizeof(int)*maxn);
}
void addedge(int u, int v, int cap, int cost)
{
	edge[tol].to = v;
	edge[tol].cap = cap;
	edge[tol].cost = cost;
	edge[tol].flow = 0;
	edge[tol].next = head[u];
	head[u] = tol++;
	edge[tol].to = u;
	edge[tol].cap = 0;
	edge[tol].cost = -cost;
	edge[tol].flow = 0;
	edge[tol].next = head[v];
	head[v] = tol++;
}
bool spfa(int s, int t)
{
	queue<int>q;
	memset(dist, 0x3f, sizeof(int)*maxn);
	memset(vis, 0, sizeof(vis));
	memset(pre, -1, sizeof(int)*maxn);
	dist[s] = 0;
	vis[s] = true;
	q.push(s);
	while (!q.empty())
	{
		int u = q.front();
		q.pop();
		vis[u] = false;
		for (int i = head[u]; i != -1; i = edge[i].next)
		{
			int v = edge[i].to;
			if (edge[i].cap > edge[i].flow &&
				dist[v] > dist[u] + edge[i].cost)
			{
				dist[v] = dist[u] + edge[i].cost;
				pre[v] = i;
				if (!vis[v])
				{
					vis[v] = true;
					q.push(v);
				}
			}
		}
	}
	if (pre[t] == -1)return false;
	else return true;
}
//返回的是最大流,cost存的是最小费用
int minCostMaxflow(int s, int t, int &cost)
{
	int flow = 0;
	cost = 0;
	while (spfa(s, t))
	{
		int Min = INF;
		for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to])
		{
			if (Min > edge[i].cap - edge[i].flow)
				Min = edge[i].cap - edge[i].flow;
		}
		for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to])
		{
			edge[i].flow += Min;
			edge[i ^ 1].flow -= Min;
			cost += edge[i].cost * Min;
		}
		flow += Min;
	}
	return flow;
}
int shop[55][55], place[55][55], goods[55][55][55];
int main()
{
	//freopen("input.txt","r",stdin);
	//freopen("output.txt","w",stdout);
	//ios::sync_with_stdio(false);
	//cin.tie(0); cout.tie(0);
	//ifstream in;
	//in.open("input.txt", ios::in);
	int n, m, k;
	while (scanf("%d%d%d", &n, &m, &k) != EOF)
	{
		if (n == 0 && m == 0 && k == 0)
			break;
		int ans = 0, sum = 0;
		int t1 = 0, t2 = 0;
		for (int i = 0; i < n; ++i)
		{
			for (int j = 0; j < k; ++j)
				scanf("%d", &shop[i][j]);
		}
		for (int i = 0; i < m; ++i)
		{
			for (int j = 0; j < k; ++j)
				scanf("%d", &place[i][j]);
		}
		for (int x = 0; x < k; ++x)
		{
			for (int i = 0; i < n; ++i)
			{
				for (int j = 0; j < m; ++j)
					scanf("%d", &goods[x][i][j]);
			}
		}
		for (int x = 0; x < k; ++x)
		{
			init(n + m + 2);
			t1 = 0; t2 = 0;
			for (int i = 0; i < m; ++i)
			{
				if (place[i][x]>0)
					addedge(0, i + 1, place[i][x], 0);
				t1 += place[i][x];
			}
			for (int i = 0; i < n; ++i)
			{
				if (shop[i][x]>0)
					addedge(m + i + 1, m + n + 1, shop[i][x], 0);
				t2 += shop[i][x];
			}
			if (t1 < t2)
			{
				ans = -1; break;
			}
			for (int i = 0; i < n; ++i)
			{
				for (int j = 0; j < m; ++j)
					addedge(j + 1, m + i + 1, INF, goods[x][i][j]);
			}
			t1 = 0; t2 = 0;
			t2 = minCostMaxflow(0, m + n + 1, t1);
			ans += t1;
		}
		printf("%d\n", ans);
	}
	//while (1);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/code12hour/article/details/52075615