【费用流】【网络流24题】【P4014】 分配问题
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];
}
【费用流】【网络流24题】【P4014】 分配问题的更多相关文章
- LG2770/LOJ6122 航空路线问题 费用流 网络流24题
问题描述 LG2770 LOG6122 题解 教训:关掉流同步之后就不要用其他输入输出方式了. 拆点. 两个拆点之间连\((1,1)\),其他连\((1,0)\) \(\mathrm{Code}\) ...
- Libre 6012 「网络流 24 题」分配问题 (网络流,费用流)
Libre 6012 「网络流 24 题」分配问题 (网络流,费用流) Description 有n件工作要分配给n个人做.第i个人做第j件工作产生的效益为\(c_{ij}\).试设计一个将n件工作分 ...
- cogs_14_搭配飞行员_(二分图匹配+最大流,网络流24题#01)
描述 http://cojs.tk/cogs/problem/problem.php?pid=14 有一些正飞行员和副飞行员,给出每个正飞行员可以和哪些副飞行员一起飞.一架飞机上必须一正一副,求最多多 ...
- 2018.10.14 loj#6012. 「网络流 24 题」分配问题(费用流)
传送门 费用流水题. 依然是照着题意模拟建边就行了. 为了练板子又重新写了一遍费用流. 代码: #include<bits/stdc++.h> #define N 305 #define ...
- 【刷题】LOJ 6012 「网络流 24 题」分配问题
题目描述 有 \(n\) 件工作要分配给 \(n\) 个人做.第 \(i\) 个人做第 \(j\) 件工作产生的效益为 \(c_{ij}\) .试设计一个将 \(n\) 件工作分配给 \(n\) ...
- 【PowerOJ1753&网络流24题】分配问题(KM)
题意: 思路:费用流可做 最好的算法是KM板子 #include<bits/stdc++.h> using namespace std; typedef long long ll; typ ...
- Luogu P4014 「 网络流 24 题 」分配问题
解题思路 还是建立超级源点和超级汇点,又因为题目给出规定一个人只能修一个工件,所以建图的时候还要讲容量都设为$1$. 人的编号是$1\rightarrow n$,工件的编号是$n+1\rightarr ...
- 【LOJ】 #6012. 「网络流 24 题」分配问题
题解 又写了一遍KM算法,这题刚好是把最大最小KM拼在一起写的,感觉比较有记录价值 感觉KM始终不熟啊QAQ 算法流程大抵如下,原理就是每次我们通过减少最少的匹配量达成最大匹配,所以获得的一定是最大价 ...
- LG2766 最长不下降子序列问题 最大流 网络流24题
问题描述 LG2766 题解 \(\mathrm{Subtask 1}\) 一个求最长不下降子序列的问题,发现\(n \le 500\),直接\(O(n^2)\)暴力DP即可. \(\mathrm{S ...
- 【网络流24题】最长k可重线段集(费用流)
[网络流24题]最长k可重线段集(费用流) 题面 Cogs的数据有问题 Loj 洛谷 题解 这道题和最长k可重区间集没有区别 只不过费用额外计算一下 但是,还是有一点要注意的地方 这里可以是一条垂直的 ...
随机推荐
- (第十一周)Beta—review阶段成员贡献分
项目名:食物链教学工具 组名:奋斗吧兄弟 组长:黄兴 组员:李俞寰.杜桥.栾骄阳.王东涵 个人贡献分=基础分+表现分 基础分=5*5*0.5/5=2.5 成员得分如下: 成员 基础分 表现分 个人贡献 ...
- [buaa-SE-2017]个人作业-回顾
个人作业-回顾 提问题的博客:[buaa-SE-2017]个人作业-Week1 Part1: 问题的解答和分析 1.1 问题:根据书中"除了前20的学校之外,计科和软工没有区别"所 ...
- [BUAA OO]第二次博客作业
第五次作业 这次作业是电梯系列作业的终极版,要求是使用多线程实现三部电梯的运行.这次作业的难点在于第一次运用多线程技术,对于线程中的行为并不了解,以及电梯功能的实现(如果之前作业采取的是扫描指令队列预 ...
- 树莓派 Raspberry-Pi 折腾系列:系统安装及一些必要的配置
入手树莓派将近一个月了,很折腾,许多资源不好找,也很乱.简单整理一下自己用到的东西,方便以后自己或别人继续折腾. 0. 操作系统下载 树莓派官方 Raspbian 系统下载:http://www.ra ...
- mysql 官方集群
一.环境准备(Centos7,mysql-cluster-gpl-7.5.6-linux-glibc2.5-x86_64.tar.gz) 卸载以前安装的Mysql 或者 mariadb yum -y ...
- 注册表:DWORD
百度百科 DWORD全称Double Word,是指注册表的键值,每个word为2个字节的长度,DWORD 双字即为4个字节,每个字节是8位,共32位. 在键值项窗口空白处单击右键,选择“新建”菜单项 ...
- Js apply方法详解,及其apply()方法的妙用
Js apply方法详解 我在一开始看到javascript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示例,总算是看的有点眉目了,在这 ...
- [转帖]select提高并发,select和poll、epoll的区别(杂)
同步IO和异步IO,阻塞IO和非阻塞IO分别是什么,到底有什么区别?不同的人在不同的上下文下给出的答案是不同的.所以先限定一下本文的上下文. https://www.2cto.com/kf/20161 ...
- [转]正确设置nginx/php-fpm/apache权限
核心总结:php-fpm/apache 进程所使用的用户,不能是网站文件所有者. 凡是违背这个原则,则不符合最小权限原则. 根据生产环境不断反馈,发现不断有 php网站被挂木马,绝大部分原因是因为权限 ...
- java异常处理的throw和throws的区别
1. 区别 throws是用来声明一个方法可能抛出的所有异常信息,throws是将异常声明但是不处理,而是将异常往上传,谁调用我就交给谁处理.而throw则是指抛出的一个具体的异常类型. 2.分别介绍 ...