题目描述
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
#include #include #include 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 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; }