POJ 2516 Minimum Cost (最小费用最大流)
Posted claireyuancy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 2516 Minimum Cost (最小费用最大流)相关的知识,希望对你有一定的参考价值。
POJ 2516 Minimum Cost
题意:有M个仓库。N个商人。K种物品。先输入N,M。K。然后输入N行K个数,每一行代表一个商人要购买的物品,当中K个数分别表示要购买的每件商品数。
然后是M行K个数,每行表示仓库里的情况,当中K个数分别每种物品的库存量。
接下来是K个矩阵,每一个矩阵为N*M,分别表示第K种物品从M个仓库运到第N个商人的花费。问是否能合理安排,使得花费最少。假设不行就输出-1。
思路:
一開始的时候。居然构造了N*K + M*K的点,必定TLE了。
后来发现,事实上能够对每一种物品做一次最小费用最大流。然后对每次费用求和就可以。
只是一開始要先推断是否可以满足条件。仅仅须要对每一件商品的需求和供应求和。每件商品的供大于等于求便一定能有答案。
代码:
/* ID: [email protected] PROG: LANG: C++ */ #include<map> #include<set> #include<queue> #include<stack> #include<cmath> #include<cstdio> #include<vector> #include<string> #include<fstream> #include<cstring> #include<ctype.h> #include<iostream> #include<algorithm> using namespace std; #define INF (1 << 30) #define LINF (1LL << 60) #define PI acos(-1.0) #define mem(a, b) memset(a, b, sizeof(a)) #define rep(i, a, n) for (int i = a; i < n; i++) #define per(i, a, n) for (int i = n - 1; i >= a; i--) #define eps 1e-6 #define debug puts("===============") #define pb push_back #define mkp make_pair #define all(x) (x).begin(),(x).end() #define fi first #define se second #define SZ(x) ((int)(x).size()) #define POSIN(x,y) (0 <= (x) && (x) < n && 0 <= (y) && (y) < m) typedef long long ll; typedef unsigned long long ULL; const int maxn = 5555; const int maxm = 500000; struct node { int v, cap, nxt, cost; } e[maxm * 2]; int g[maxn], cnt, st, ed, n, m; int ans, flow; int N, M, K; int nk[60][60], mk[60][60]; void add(int u, int v, int cap, int cost) { e[++cnt].v = v; e[cnt].cap = cap; e[cnt].cost = cost; e[cnt].nxt = g[u]; g[u] = cnt; e[++cnt].v = u; e[cnt].cap = 0; e[cnt].cost = -cost; e[cnt].nxt = g[v]; g[v] = cnt; } void init(int k) { cnt = 1; ans = flow = 0; memset(g, 0, sizeof(int) * (M + N + 10)); // 加边 st = 0, ed = M + N + 1, n = ed; for (int i = 1; i <= M; i++) add(st, i, mk[i][k], 0); for (int i = 1; i <= N; i++) add(i + M, ed, nk[i][k], 0); int c; for (int i = 1; i <= N; i++) { for (int j = 1; j <= M; j++) { scanf("%d", &c); add(j, i + M, INF, c); } } } int dis[maxn], que[maxn], pre[maxn]; bool vis[maxn]; bool spfa() { int font = 0, rear = 1; for(int i = 0; i <= n; i ++) { dis[i] = INF; vis[i] = false; } dis[st] = 0; que[0] = st; vis[st] = true; while(rear != font) { int u = que[font++]; font %= n; vis[u] = false; for(int i = g[u]; i; i = e[i].nxt) { int v = e[i].v; if(e[i].cap && dis[v] > dis[u] + e[i].cost) { dis[v] = dis[u] + e[i].cost; pre[v] = i; if(!vis[v]) { vis[v] = true; que[rear++] = v; rear %= n; } } } } if(dis[ed] == INF) return false; return true; } void augment() { int u, p, mi = INF; for(u = ed; u != st; u = e[p ^ 1].v) { p = pre[u]; mi = min(mi, e[p].cap); } for(u = ed; u != st; u = e[p ^ 1].v) { p = pre[u]; e[p].cap -= mi; e[p ^ 1].cap += mi; ans += mi * e[p].cost; // cost记录的为单位流量费用,必须得乘以流量。 } flow += mi; } int MCMF(int k) { init(k); while(spfa()) augment(); return ans; } bool get() { int n_k[110] = {0}, m_k[110] = {0}; int c; rep(i, 1, N + 1) rep(j, 1, K + 1) { scanf("%d", &c); n_k[j] += c; nk[i][j] = c; } rep(i, 1, M + 1) rep(j, 1, K + 1) { scanf("%d", &c); m_k[j] += c; mk[i][j] = c; } for (int i = 1; i <= K; i++) if (n_k[i] > m_k[i]) return false; return true; } int main () { while(~scanf("%d%d%d", &N, &M, &K), N || M || K) { if (get()) { int tot = 0; for (int i = 1; i <= K; i++) { tot += MCMF(i); } printf("%d\n", tot); } else { int c; rep(i, 0, K) rep(j, 0, N) rep(k, 0, M) scanf("%d", &c); puts("-1"); } } return 0; }
以上是关于POJ 2516 Minimum Cost (最小费用最大流)的主要内容,如果未能解决你的问题,请参考以下文章
Minimum Cost POJ - 2516 (模板题 spfa最小费用最大流)