網路流24題 P4015 運輸問題 (最大和最小費用流)
阿新 • • 發佈:2018-12-13
題目描述
WW 公司有 mm 個倉庫和 nn 個零售商店。第 ii 個倉庫有 a_iai 個單位的貨物;第 jj 個零售商店需要 b_jbj 個單位的貨物。
貨物供需平衡,即\sum\limits_{i=1}^{m}a_i=\sum\limits_{j=1}^{n}b_ji=1∑mai=j=1∑nbj。
從第 ii 個倉庫運送每單位貨物到第 jj 個零售商店的費用為 c_{ij}cij 。
試設計一個將倉庫中所有貨物運送到零售商店的運輸方案,使總運輸費用最少。
輸入輸出格式
輸入格式:
第 11 行有 22 個正整數 mm 和 nn,分別表示倉庫數和零售商店數。
接下來的一行中有 mm 個正整數 a_iai,表示第 ii 個倉庫有 a_iai個單位的貨物。
再接下來的一行中有 nn 個正整數 b_jbj,表示第 jj 個零售商店需要 b_jbj 個單位的貨物。
接下來的 mm 行,每行有 nn 個整數,表示從第 ii 個倉庫運送每單位貨物到第 jj 個零售商店的費用 c_{ij}cij。
輸出格式:
兩行分別輸出最小運輸費用和最大運輸費用。
輸入輸出樣例
輸入樣例#1: 複製
2 3 220 280 170 120 210 77 39 105 150 186 122輸出樣例#1: 複製
48500 69140說明
1 \leq n, m \leq 1001≤n,m≤100
源點向倉庫連容量為ai和費用為0的邊 商店向匯點連容量為bi和費用為0的邊 每個倉庫向每個商店為容量為inf,費用為ci的邊。 一道裸題
#pragma GCC optimize(2) #include<stdio.h> #include<algorithm> #include<string.h> #include<queue> using namespace std; const int maxn = 1e5; const int inf = 0x3f3f3f3f; typedef long long ll; int head[maxn], dis[maxn], a[maxn], b[maxn], f[1005][1005], vis[maxn], pre[maxn]; int n, m, tot; struct node { int v, cap, flow, cost, next, u; }edge[maxn*2]; void init() { tot = 0; memset(head, -1, sizeof(head)); return; } void addedge(int u, int v, int cap, int cost) { edge[tot].u = u; edge[tot].v = v; edge[tot].cap = cap; edge[tot].cost = cost; edge[tot].flow = 0; edge[tot].next = head[u]; head[u] = tot++; edge[tot].u = v; edge[tot].v = u; edge[tot].cap = 0; edge[tot].flow = 0; edge[tot].cost = -cost; edge[tot].next = head[v]; head[v] = tot++; return; } bool spfa(int s,int t) { for (int i = 0; i <= t; i++) { dis[i] = inf; vis[i] = false; pre[i] = -1; } queue<int>q; dis[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].v; if (edge[i].cap > edge[i].flow&&dis[v] > dis[u] + edge[i].cost) { dis[v] = dis[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; } int mincost(int s,int t) { int ans = 0; while (spfa(s,t)) { int _min = inf; for (int i = pre[t]; i != -1; i = pre[edge[i].u]) { _min = min(_min, edge[i].cap ); } for (int i = pre[t]; i != -1; i = pre[edge[i].u]) { edge[i].cap -= _min; edge[i ^ 1].cap += _min; } ans += _min * dis[t]; } return ans; } int main() { //freopen("C://input.txt", "r", stdin); scanf("%d%d", &m, &n); init(); int s = 0, t = n + m + 1; for (int i = 1; i <= m; i++) { scanf("%d", &a[i]); addedge(s, i, a[i], 0); } for (int i = 1; i <= n; i++) { scanf("%d", &b[i]); addedge(i + m, t, b[i], 0); } for (int i = 1; i <= m; i++) { for (int j = m + 1; j <= n + m; j++) { scanf("%d", &f[i][j]); addedge(i, j, inf, f[i][j]); } } printf("%d\n", mincost(s, t)); init(); for (int i = 1; i <= m; i++) { addedge(s, i, a[i], 0); } for (int i = 1; i <= n; i++) { addedge(i + m, t, b[i], 0); } for (int i = 1; i <= m; i++) { for (int j = m + 1; j <= n + m; j++) { addedge(i, j, inf, -f[i][j]); } } printf("%d\n", -mincost(s, t)); return 0; }