题解

又写了一遍KM算法,这题刚好是把最大最小KM拼在一起写的,感觉比较有记录价值

感觉KM始终不熟啊QAQ

算法流程大抵如下,原理就是每次我们通过减少最少的匹配量达成最大匹配,所以获得的一定是最大价值

1.我们先给左部点求一个期望大小,如果是最大KM,期望大小就是最大的那条边的权值,如果是最小KM,期望大小就是最小的那条边的权值

2.然后跑二分图匹配,两个点能匹配的条件是左点\(u\)的期望值加右点\(v\)的期望值刚好是边权

3.给无法访问的点更新断层大小,如果是最小匹配,那么断层就是\(c[u][v] - (ex_l[u] + ex_r[v])\),如果是最大匹配,就是\((ex_l[u] + ex_r[v]) - c[u][v]\)

4.在没有被访问的右点里寻找最小的减少量\(d\)

5.给访问过的左点和右点,如果是最小匹配,左点加上\(d\),因为要包括进一些更大的边,右点减去\(d\),如果是最大匹配,左点减去\(d\),因为要包括进一些更小的边,右点加上\(d\)

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int, int>
#define pdi pair<db, int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 205
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template <class T>
void read(T &res) {
res = 0;
char c = getchar();
T f = 1;
while (c < '0' || c > '9') {
if (c == '-')
f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template <class T>
void out(T x) {
if (x < 0) {
x = -x;
putchar('-');
}
if (x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
int N;
int c[105][105];
int ex_l[105], ex_r[105], slack[105], matc[105];
bool vis_l[105], vis_r[105];
bool match(int u, int on) {
vis_l[u] = 1;
for (int v = 1; v <= N; ++v) {
if (!vis_r[v]) {
if (vis_r[v])
continue;
int gap;
if (on == 0)
gap = c[u][v] - ex_l[u] - ex_r[v];
else
gap = ex_l[u] + ex_r[v] - c[u][v];
if (gap == 0) {
vis_r[v] = 1;
if (!matc[v] || match(matc[v], on)) {
matc[v] = u;
return true;
}
} else
slack[v] = min(slack[v], gap);
}
}
return false;
}
int KM(int on) {
for (int i = 1; i <= N; ++i) {
ex_r[i] = 0;
if (on == 0)
ex_l[i] = 0x7fffffff;
else
ex_l[i] = 0;
for (int j = 1; j <= N; ++j) {
if (on == 0)
ex_l[i] = min(ex_l[i], c[i][j]);
else
ex_l[i] = max(ex_l[i], c[i][j]);
}
}
memset(matc, 0, sizeof(matc));
for (int i = 1; i <= N; ++i) {
for (int j = 1; j <= N; ++j) slack[j] = 0x7fffffff;
while (1) {
memset(vis_l, 0, sizeof(vis_l));
memset(vis_r, 0, sizeof(vis_r));
if (match(i, on))
break;
int d = 0x7fffffff;
for (int j = 1; j <= N; ++j) {
if (!vis_r[j])
d = min(d, slack[j]);
}
for (int j = 1; j <= N; ++j) {
if (on == 0) {
if (vis_l[j])
ex_l[j] += d;
if (vis_r[j])
ex_r[j] -= d;
else
slack[j] -= d;
} else {
if (vis_l[j])
ex_l[j] -= d;
if (vis_r[j])
ex_r[j] += d;
else
slack[j] -= d;
}
}
}
}
int res = 0;
for (int v = 1; v <= N; ++v) {
res += c[matc[v]][v];
}
return res;
}
void Solve() {
read(N);
for (int i = 1; i <= N; ++i) {
for (int j = 1; j <= N; ++j) {
read(c[i][j]);
}
}
out(KM(0));
enter;
out(KM(1));
enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in", "r", stdin);
#endif
Solve();
return 0;
}

【LOJ】 #6012. 「网络流 24 题」分配问题的更多相关文章

  1. 【刷题】LOJ 6012 「网络流 24 题」分配问题

    题目描述 有 \(n\) 件工作要分配给 \(n\) 个人做.第 \(i\) 个人做第 \(j\) 件工作产生的效益为 \(c_{ij}\) ​​.试设计一个将 \(n\) 件工作分配给 \(n\) ...

  2. 2018.10.14 loj#6012. 「网络流 24 题」分配问题(费用流)

    传送门 费用流水题. 依然是照着题意模拟建边就行了. 为了练板子又重新写了一遍费用流. 代码: #include<bits/stdc++.h> #define N 305 #define ...

  3. Libre 6012 「网络流 24 题」分配问题 (网络流,费用流)

    Libre 6012 「网络流 24 题」分配问题 (网络流,费用流) Description 有n件工作要分配给n个人做.第i个人做第j件工作产生的效益为\(c_{ij}\).试设计一个将n件工作分 ...

  4. 【刷题】LOJ 6227 「网络流 24 题」最长k可重线段集问题

    题目描述 给定平面 \(\text{xoy}\) 上 \(n\) 个开线段组成的集合 \(\text{I}\) ,和一个正整数 \(k\) ,试设计一个算法. 从开线段集合 \(\text{I}\) ...

  5. [luogu_P1251][LOJ#6008]「网络流 24 题」餐巾计划

    [luogu_P1251][LOJ#6008]「网络流 24 题」餐巾计划 试题描述 一个餐厅在相继的 \(N\) 天里,第 \(i\) 天需要 \(R_i\) 块餐巾 \((i=l,2,-,N)\) ...

  6. [LOJ#6002]「网络流 24 题」最小路径覆盖

    [LOJ#6002]「网络流 24 题」最小路径覆盖 试题描述 给定有向图 G=(V,E).设 P 是 G 的一个简单路(顶点不相交)的集合.如果 V 中每个顶点恰好在 P 的一条路上,则称 P 是  ...

  7. loj #6014. 「网络流 24 题」最长 k 可重区间集

    #6014. 「网络流 24 题」最长 k 可重区间集 题目描述 给定实直线 L LL 上 n nn 个开区间组成的集合 I II,和一个正整数 k kk,试设计一个算法,从开区间集合 I II 中选 ...

  8. loj #6013. 「网络流 24 题」负载平衡

    #6013. 「网络流 24 题」负载平衡 题目描述 G 公司有 n nn 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等.如何用最少搬运量可以使 n nn 个仓库的库存数量相同.搬运货物时 ...

  9. loj #6122. 「网络流 24 题」航空路线问题

    #6122. 「网络流 24 题」航空路线问题 题目描述 给定一张航空图,图中顶点代表城市,边代表两个城市间的直通航线.现要求找出一条满足下述限制条件的且途经城市最多的旅行路线. 从最西端城市出发,单 ...

随机推荐

  1. 洛谷 P1412 经营与开发 解题报告

    P1412 经营与开发 题目描述 \(4X\)概念体系,是指在\(PC\)战略游戏中一种相当普及和成熟的系统概念,得名自4个同样以"\(EX\)"为开头的英语单词. \(eXplo ...

  2. 洛谷 P3629 [APIO2010]巡逻 解题报告

    P3629 [APIO2010]巡逻 题目描述 在一个地区中有 n 个村庄,编号为 1, 2, ..., n.有 n – 1 条道路连接着这些村 庄,每条道路刚好连接两个村庄,从任何一个村庄,都可以通 ...

  3. luogu2679 [NOIp2015]子串 (dp)

    设f[i][j][k][b]表示在A串第i位.这是第j组.B串第k位.i号选不选(b=0/1) 那么就有$f[i][j][k][1]=(A[i]==B[k])*(f[i-1][j-1][k][0]+f ...

  4. 函数、可变参数、keyword-only参数、实参解构

    函数的数学定义:y=f(x) ,y是x的函数,x是自变量.y=f(x0, x1, ..., xn) python中的函数: 由函数名称.参数列表.和若干语句组成的语句块构成,完成一定的功能,是组织代码 ...

  5. bzoj2134: 单选错位(trie)

    预处理前后缀异或和,用trie得到前后缀最大答案,枚举中间点把左右两边加起来就是当前中间点的最大答案了...这个操作没见过,比较有意思,记录一下 #include<iostream> #i ...

  6. CRT && exCRT模板

    CRT从各种方面上都吊打exCRT啊...... 短,好理解... 考虑构造bi使得bi % pi = ai,bi % pj = 0.然后全加起来就行了. 显然bi的构造就是ai * (P/pi) * ...

  7. SSM搭建Spring单元测试环境

    原文链接:https://jingyan.baidu.com/article/93f9803f5a97a4e0e46f55c8.html SSM搭建Spring单元测试环境

  8. div 内table 居中实现代码

    有时候在一个div里面添加一个表格,如想让它居住排列,需要做如下的操作. css代码:   代码如下: #dlgReply { /*display: table-cell; text-align: c ...

  9. RPC与RMI的区别

    分布式项目按照以下发展经历了以下技术: CORBA: RMI:基于远程接口的调用 RMI-RROP:这是RMI与CORBA的结合,用在了EJB技术上,EJB留给世界上是优秀的理论和糟糕的架构. WEB ...

  10. Java基础-Java数据类型

    Java基础-Java数据类型 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.数据类型的作用 数据类型就是一组值,以及这一组值上的操作,数据类型可以决定数据的存储方式,取值范围 ...