Description

有 \(n\) 件工作要分配给 \(n\) 个人做。第 \(i\) 个人做第 \(j\) 件工作产生的效益为 \(C_{i,j}\) 。试设计一个将 \(n\) 件工作分配给 \(n\) 个人做的分配方案,使产生的总效益最大。

Input

文件的第 \(1\) 行有 \(1\) 个正整数 \(n\),表示有 \(n\) 件工作要分配给 \(n\) 个人做。

接下来的 \(n\) 行中,每行有 \(n\) 个整数 \(C_{i,j}\),表示第 \(i\) 个人做第 \(j\) 件工作产生的效益为 \(C_{ij}\)。

Output

两行分别输出最小总效益和最大总效益。

Hint

\(1~\leq~n~\leq~100\)

Solution

先考虑最小收益,由于必须所有的工作都被分配,所以这个限制可以转化为最大流,由于是最小费用,所以可以转化成最小费用最大流。

将人和工作之间连边,容量为 \(1\),费用为效益。建立超级源点超级汇点,源点连向人,容量为 \(1\),费用为 \(0\)。工作连向汇点,容量为 \(1\),费用为 \(0\)。这样保证了一个任务选且被选一次,同时费用即为收益。

考虑最大收益:将所有费用取相反数,求出答案再取相反即可。

Code

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#ifdef ONLINE_JUDGE
#define freopen(a, b, c)
#endif
#define ci const int
#define cl const long long typedef long long int ll; namespace IPT {
const int L = 1000000;
char buf[L], *front=buf, *end=buf;
char GetChar() {
if (front == end) {
end = buf + fread(front = buf, 1, L, stdin);
if (front == end) return -1;
}
return *(front++);
}
} template <typename T>
inline void qr(T &x) {
char ch = IPT::GetChar(), lst = ' ';
while ((ch > '9') || (ch < '0')) lst = ch, ch=IPT::GetChar();
while ((ch >= '0') && (ch <= '9')) x = (x << 1) + (x << 3) + (ch ^ 48), ch = IPT::GetChar();
if (lst == '-') x = -x;
} template <typename T>
inline void ReadDb(T &x) {
char ch = IPT::GetChar(), lst = ' ';
while ((ch > '9') || (ch < '0')) lst = ch, ch = IPT::GetChar();
while ((ch >= '0') && (ch <= '9')) x = x * 10 + (ch ^ 48), ch = IPT::GetChar();
if (ch == '.') {
ch = IPT::GetChar();
double base = 1;
while ((ch >= '0') && (ch <= '9')) x += (ch ^ 48) * ((base *= 0.1)), ch = IPT::GetChar();
}
if (lst == '-') x = -x;
} namespace OPT {
char buf[120];
} template <typename T>
inline void qw(T x, const char aft, const bool pt) {
if (x < 0) {x = -x, putchar('-');}
int top=0;
do {OPT::buf[++top] = static_cast<char>(x % 10 + '0');} while (x /= 10);
while (top) putchar(OPT::buf[top--]);
if (pt) putchar(aft);
} const int maxn = 210;
const int INF = 0x3f3f3f3f; struct Edge {
int from, to, flow, fee;
Edge *nxt, *bk;
};
Edge *hd[maxn], *pre[maxn];
inline void cont(Edge *u, Edge *v, int from, int to, int fl, int fe) {
u->from = from; u->to = to; u->flow = fl; u->fee = fe; u->bk = v;
u->nxt = hd[from]; hd[from] = u;
}
inline void conet(int from, int to, int fl, int fe) {
Edge *u = new Edge, *v = new Edge;
cont(u, v, from, to, fl, fe); cont(v, u, to, from, 0, -fe);
} int n, s, t, ans;
int cost[maxn], maxflw[maxn], MU[maxn][maxn];
bool inq[maxn];
std::queue<int>Q; bool SPFA();
void argu(); int main() {
freopen("1.in", "r", stdin);
qr(n);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
qr(MU[i][j]); conet(i, j + n, 1, MU[i][j]);
}
}
s = (n << 1) | 1; t = (n << 1) + 2;
for (int i = 1; i <= n; ++i) conet(s, i, 1, 0);
for (int i = n + 1; i < s; ++i) conet(i, t, 1, 0);
ans = 0;
while (SPFA()) argu();
qw(ans, '\n', true);
memset(hd, 0, sizeof hd);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) conet(i, j + n, 1, -MU[i][j]);
}
for (int i = 1; i <= n; ++i) conet(s, i, 1, 0);
for (int i = n + 1; i < s; ++i) conet(i, t, 1, 0);
ans = 0;
while (SPFA()) argu();
qw(-ans, '\n', true);
return 0;
} bool SPFA() {
memset(cost, 0x3f, sizeof cost);
memset(inq, 0, sizeof inq);
memset(pre, 0, sizeof pre);
memset(maxflw, 0, sizeof maxflw);
cost[s] = 0; Q.push(s); maxflw[s] = INF;
while (!Q.empty()) {
int h = Q.front(); Q.pop(); inq[h] = false;
if (!maxflw[h]) continue;
for (Edge *e = hd[h]; e; e = e->nxt) if (e->flow > 0) {
int to = e->to;
if (cost[to] > (cost[h] + e->fee)) {
cost[to] = cost[h] + e->fee;
maxflw[to] = std::min(maxflw[h], e->flow);
if (!inq[to]) Q.push(to);
inq[to] = true; pre[to] = e;
}
}
}
return cost[t] != INF;
} void argu() {
for (Edge *e = pre[t]; e; e = pre[e->from]) {
e->flow -= maxflw[t];
e->bk->flow += maxflw[t];
}
ans += maxflw[t] * cost[t];
}

最新文章

  1. October 21st 2016 Week 43rd Friday
  2. AIX 环境下整理文件系统碎块
  3. C#Excel的导入与导出
  4. css3颜色渐变
  5. php防注入留言板(simple)
  6. hdu 1575 Tr A
  7. Android 基于Netty的消息推送方案之对象的传递(四)
  8. Java中的各种o
  9. UltraEdit的语法高亮显示配置
  10. 某大神C#框架后台发送信息的查找及破解
  11. Asp.Net 常用工具类---Config操作(7)
  12. angular指令笔记(一):ng-options
  13. Ambari源代码分析之Resource.Type与ResourceProvider相应关系
  14. JavaScript创建对象的方式
  15. 『OpenCV3』基于色彩分割图片
  16. POJ2516 Minimum Cost【最小费用最大流】
  17. git常用命令二
  18. numpy 数组迭代Iterating over arrays
  19. Ansible--01
  20. Git系统学习网址

热门文章

  1. Homebrew1.5之后安装PHP和扩展
  2. iframe子页面position的fixed
  3. 【Oracle】存储过程在字符串单引号&#39;内拼接单引号&#39;
  4. Navicat将oracle中数据复制到mysql
  5. spring boot之创建web项目并访问jsp页面
  6. Scrum Meeting 10.23
  7. 私人助手(Alpha)版使用说明
  8. “Gogoing”改进方案
  9. 深入理解mybatis
  10. Internet History, Technology and Security (Week8)