POJ 2516 Minimum Cost (最小费用最大流)

来源:互联网 发布:淘宝布衣柜 编辑:程序博客网 时间:2024/05/17 06:45
题目类型  最小费用最大流

题目意思
给出最多50个用户的最多50种物品的需求数量 和 最多50个供应商的相应物品的供给数量
已知对于某种物品某个用户从某个供应商处拿数量1的货的费用 问要满足所有用户所有种类物品的需求的最少费用, 不能满足输出 -1

解题方法
因为每种物品间不会造成影响 所以每种物品分开处理
建图: 新建一个源点 s 从 s 向每个用户连一条边, 边的容量为这个用户对于当前处理的物品的需求数量, 费用为0
         新建一个汇点 t, 对于每个供应商向 t 连一条边, 边的容量为这个供应商对于当前处理的物品的供给数量, 费用为0
         即除了源点 s 和汇点 t 外还有 n 个点表示用户 还有 m 个点表示供应商 那么这 n 个点与 这 m 个点之间连边, 边的容量为无限大, 费用为
         相应用户向相应供应商取1单位货的费用
那么每次用 spfa 找出一条从 s 到 t 费用最少的增广路, 并记录能增加的最大的流量, 那么最大流就增加那个流量 费用增加这条路径的费用 * 流量
最终如果最大流等于所有用户需求的物品总数表示有合法的方案 总费用加上当前解决的物品的费用

参考代码 - 有疑问的地方在下方留言 看到会尽快回复的
#include <iostream>#include <cstdio>#include <cstring>#include <vector>#include <queue>using namespace std;const int maxn = 50 + 10;const int INF = 1<<29;struct Edge {int from, to, cap, flow, cost;Edge(int _from, int _to, int _cap, int _flow, int _cost) : from(_from), to(_to), cap(_cap), flow(_flow), cost(_cost) {}Edge() {}};int sum;struct MCMF {int n, m, s, t;vector<Edge>edges;vector<int>G[maxn*maxn];int inq[maxn*2], d[maxn*2], p[maxn*2], a[maxn*2];void init(int n) {this->n = n;for( int i=0; i<n; i++ ) G[i].clear();edges.clear();}void AddEdge(int from, int to, int cap, int cost) {edges.push_back(Edge(from, to, cap, 0, cost));edges.push_back(Edge(to, from, 0, 0, -cost));m = edges.size();G[from].push_back(m-2);G[to].push_back(m-1);}bool BellmanFord(int s, int t, int & flow, int & cost) {for( int i=0; i<n; i++ ) d[i] = INF;memset(inq, 0, sizeof(inq));d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = INF;queue<int>Q;Q.push(s);while(!Q.empty()) {int u = Q.front(); Q.pop();inq[u] = 0;for( int i=0; i<G[u].size(); i++ ) {Edge & e = edges[G[u][i]];if(e.cap > e.flow && d[e.to] > d[u] + e.cost) {d[e.to] = d[u] + e.cost;p[e.to] = G[u][i];a[e.to] = min(a[u], e.cap - e.flow);if(!inq[e.to]) { Q.push(e.to); inq[e.to] = 1; }}}}if(d[t] == INF) return false;flow += a[t];cost += d[t] * a[t];int u = t;while(u != s) {edges[p[u]].flow += a[t];edges[p[u]^1].flow -= a[t];u = edges[p[u]].from;}return true;}int Mincost(int s, int t) {int flow = 0, cost = 0;while(BellmanFord(s, t, flow, cost));if(flow < sum) return -1;else return cost;}}MC;int need[maxn][maxn], have[maxn][maxn];int main() {freopen("in", "r", stdin);int n, m, k;while(scanf("%d%d%d", &n, &m, &k), n || m || k) {for( int i=0; i<n; i++ ) for( int j=0; j<k; j++ ) {scanf("%d", &need[i][j]);}for( int i=0; i<m; i++ ) for( int j=0; j<k; j++ ) {scanf("%d", &have[i][j]);}int ans = 0;for( int h=0; h<k; h++ ) {MC.init(1+n+m+1);sum = 0;for( int i=0; i<n; i++ ) MC.AddEdge(0, 1+i, need[i][h], 0), sum += need[i][h];for( int i=0; i<m; i++ ) MC.AddEdge(1+n+i, 1+n+m, have[i][h], 0);for( int i=0; i<n; i++ ) for( int j=0; j<m; j++ ) {int tmp;scanf("%d", &tmp);MC.AddEdge(1+i, 1+n+j, INF, tmp);}if(ans == -1) continue;int tmp = MC.Mincost(0, 1+n+m);if(tmp == -1) ans = -1;else ans += tmp;}if(ans == -1) printf("-1\n");else printf("%d\n", ans);}return 0;}
0 0
原创粉丝点击