@atcoder - Japanese Student Championship 2019 Qualification - E@ Card Collector
@description@
N 个卡片放在 H*W 的方格图上,第 i 张卡片的权值为 Ai,放在 (Ri, Ci)。一个位置可以放置多张卡片。
你可以在每行捡起最多一张卡片,然后在每列捡起最多一张卡片。
求捡起的卡片权值最大和。
Constraints
所有值都是整数。
1≤N≤10^5, 1≤H,W≤10^5, 1≤Ai≤10^5, 1≤Ri≤H, 1≤Ci≤W。
Input
输入的形式如下:
N H W
R1 C1 A1
R2 C2 A2
⋮
⋮
RN CN AN
Output
输出可能的最大权和。
Sample Input
6 2 2
2 2 2
1 1 8
1 1 5
1 2 9
1 2 7
2 1 4
Sample Output
28
样例解释如下:
从第一行捡起第四张卡 A4。
从第二行捡起第六张卡 A6。
从第三行捡起第二张卡 A2。
从第四行捡起第五张卡 A5。
最后权值和 = A4 + A6 + A2 + A5 = 9 + 7 + 4 + 8 = 28。
@solution@
看到这个题就知道它一定是个网络流。
我们源点连向每个卡片,容量为 1,费用为权值;卡片连向它所在的行与列,容量为 1,费用为 0;每行每列向汇点连边,容量为 1,费用为 0。
这样建图跑出来的最大费用流就是答案。
观察这个建图,思考发现它总是先沿着卡片权值最大的路径尝试增广,且它的增广过程是不会撤回的(即以前增广过的卡片不会在某一次增广中被删掉)。
所以:我们可以考虑按权值从大到小加入每张卡片,判断每次加入的卡片是否能与之前的卡片共存。
考虑我们建出来的图实际上一个二分图,我们可以使用 hall 定理判定每次加入卡片后,图中是否依然存在完美匹配。
回想 hall 定理的内容:一个点集 S 的 size <= 它邻集 T 的 size,也可以写作 |T| - |S| >= 0。我们这里的点集的邻集就代表它们所在的行列集合。
我们尝试去找不满足 hall 定理的情况。
假如仅存在单独一个点,则 |T| - |S| = 1。如果加入一个与它不在同一行或同列的点,此时 |T| - |S| 会变大,与我们目的相悖;加入一个与它在同一行或同一列的点时,|T| - |S| 不变,但之后加入的点更有可能使得 |T| - |S| 变小,所以加入这个点更有可能不满足 hall 定理。
于是:我们通过找这个点集同一行同一列的所有点不断扩大点集,到无法扩大时再判断此时的 |T| - |S| 是否满足 hall 定理。
具体到实现,我们可以对行与列建并查集,并查集内统计这个行列集合含多少行多少列(即上文的 |T|)与这些行列上有多少卡片(即上文的 |S|)。
每次加入一张卡片就把它所在的行列集合通过并查集合并,同时维护一下。当然要在加入之前判断是否合法(即是否加入完这张卡片,它所在的集合会出现 |T| - |S| < 0)。
@accepted code@
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 100000;
struct node{
int R, C, A;
friend bool operator < (node a, node b) {
return a.A < b.A;
}
}nd[MAXN + 5];
int fa[2*MAXN + 5], key[2*MAXN + 5], siz[2*MAXN + 5];
int find(int x) {
return fa[x] = (fa[x] == x ? x : find(fa[x]));
}
int N, H, W;
int main() {
long long ans = 0;
scanf("%d%d%d", &N, &H, &W);
for(int i=1;i<=H;i++) fa[i] = i, siz[i] = 1, key[i] = 0;
for(int i=1;i<=W;i++) fa[i + H] = i + H, siz[i + H] = 1, key[i + H] = 0;
for(int i=1;i<=N;i++)
scanf("%d%d%d", &nd[i].R, &nd[i].C, &nd[i].A);
sort(nd + 1, nd + N + 1);
for(int i=N;i>=1;i--) {
int fx = find(nd[i].R), fy = find(nd[i].C + H);
if( fx == fy ) {
if( siz[fx] >= key[fx] + 1 ) {
key[fx]++;
ans += nd[i].A;
}
}
else {
if( siz[fx] + siz[fy] >= key[fx] + key[fy] + 1 ) {
siz[fx] += siz[fy], key[fx] += key[fy] + 1, fa[fy] = fx;
ans += nd[i].A;
}
}
}
printf("%lld\n", ans);
}
@details@
被老师莫名其妙拉去打这种奇怪的比赛。。。
在我印象里,现在 hall 定理的题还是算比较少的吧,记下来记下来。
@atcoder - Japanese Student Championship 2019 Qualification - E@ Card Collector的更多相关文章
- @atcoder - Japanese Student Championship 2019 Qualification - F@ Candy Retribution
目录 @description@ @solution@ @accepted code@ @details@ @description@ 请找到满足以下条件的长度为 N 的非负整数序列 A1, A2, ...
- [AtCoder] NIKKEI Programming Contest 2019 (暂缺F)
[AtCoder] NIKKEI Programming Contest 2019 本来看见这一场的排名的画风比较正常就来补一下题,但是完全没有发现后两题的AC人数远少于我补的上一份AtCoder ...
- [AtCoder] Yahoo Programming Contest 2019
[AtCoder] Yahoo Programming Contest 2019 很遗憾错过了一场 AtCoder .听说这场是涨分场呢,于是特意来补一下题. A - Anti-Adjacency ...
- HDOJ 4336 Card Collector
容斥原理+状压 Card Collector Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/O ...
- HDU 4336:Card Collector(容斥原理)
http://acm.split.hdu.edu.cn/showproblem.php?pid=4336 Card Collector Special Judge Problem Descriptio ...
- Card Collector(HDU 4336)
Card Collector Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- hdu4336 Card Collector 状态压缩dp
Card Collector Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- HDU 4336 Card Collector(动态规划-概率DP)
Card Collector Problem Description In your childhood, do you crazy for collecting the beautiful card ...
- HDU 4336 Card Collector 期望dp+状压
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4336 Card Collector Time Limit: 2000/1000 MS (Java/O ...
随机推荐
- MySQL语句错误及解决方案
1.group by查询错误 ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause and contai ...
- pycharm解决无法调用同文件夹下的文件
一.将所有的文件放在project这个根目录下面 二.添加一个空的__init__.py 文件 三.选中project根目录,点击右键选择make_directory as-->sources ...
- Nginx负载均衡反向代理
http{ upstream test.com { server 118.118.66.88:8080; } server { listen 80; server_name www.test.com; ...
- Struts_改写客户列表练习
1.CustomerAction修改放入ActionContext 2.list.jsp使用struts标签库
- CentOS6.5在VMware中安装
链接:https://pan.baidu.com/s/1ggqmHxh 密码:v04l 1.启动VMware的画面 2.点击File--->New Virtual Machine 创建一台新虚拟 ...
- 极简bootstrap file 美化样式(无需第三方插件)
原本的file上传表单非常的丑,但是又不想使用第三方插件,Bootstrap也没有相关的美化,于是用纯CSS完成,美化,JS实现功能,连BootStrap都不需要,十分简单 1.给原版丑表单隐藏了di ...
- apache添加虚拟主机(windows下)
1.打开Apache的目录下的 D:\Web\Apache\conf\httpd.conf 允许虚拟,启动虚拟配置文件 2.配置虚拟主机 打开 D:\Web\Apache\conf\extra\ht ...
- jstree设置checkbox单选
jstree设置插件checkbox只允许单选 jstree version console.log($.jstree.version); 3.3.8 单选配置参数: $.jstree.default ...
- Python判断文件和文件夹是否存在的方法
Python判断文件和文件夹是否存在的方法 这篇文章主要介绍了Python判断文件和文件夹是否存在的方法,本文还讲解了判断是否为文件或者目录的方法.os.path.lexist的作用.FTP中判断文件 ...
- freemarker 取值(插值)(转)
Java数据模型 1)基本数据类型取值 八种基本的java类型:byte.short.int.long:float,double:char:boolean 对应的封装类型:Byte.Short.Int ...