@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 ...
随机推荐
- cookie记录
登录页面引用: <script src="/jquery.cookie.js"></script> 登录页面jq: var telphone = $('[n ...
- 码云及git使用
首次使用码云,将本地文件与之关联(创建仓库之后的页面截图) git -- 版本控制(协同开发软件) git add . # 将当前文件下所有内容添加到临时缓存区 git commit -m " ...
- Oracle JOB的建立,定时执行任务
Oracle JOB的建立,定时执行任务 oracle job的相关设置 next date: 2010-12-28 18:05:00 interval: to_date(to_char(sysdat ...
- day18 11.复习
其实以前写的每条SQL语句都是有事务的,因为它默认的事务是autocommit=on(自动事务).mysql的autocommit是on,oracle的autocommit是off.
- 内核、中断和网络 $ sysctl -a | grep ...$ cat /proc/interrupts$ cat /proc/net/ip_conntrack /* may take some time on busy servers */$ netstat$ ss -s
你的中断请求是否是均衡地分配给CPU处理,还是会有某个CPU的核因为大量的网络中断请求或者RAID请求而过载了? SWAP交换的设置是什么?对于工作站来说swappinness 设为 60 就很好, ...
- NOIP模拟 9.09
AK300分 果实计数 (count.pas/.c/.cpp) 时间限制:1s,空间限制32MB 题目描述: 淘淘家有棵奇怪的苹果树,这棵树共有n+1层,标号为0~n.这棵树第0层只有一个节点,为根节 ...
- 转:解决Onethink上传视频的问题 超棒的解决方案
用过Onethink的都知道,它是不能上传视频的. 有人想到用上传附件的方式上传视频,但是结果……就是提示没有上传文件. 要是正常上传个一两兆的图片啊,压缩文件什么的还是可以的. 所以,重点来了 怎么 ...
- Data Visualisation Cheet Sheet
Univariate plotting with pandas import pandas as pd reviews = pd.read_csv() reviews.head() //bar rev ...
- React 按需加载 - 代码分隔
代码分隔 我们现在大多数React项目都是以Webpack 或者 Browserify等将一堆的jsx文件组织一起,并且由一个类似index.js的入口文件串联起来的单页面web页面. 例如: // ...
- spring security四种实现方式
spring security四种实现方式 spring(20) > 目录(?)[+] 最简单配置spring-securityxml实现1 实现UserDetailsService 实现动态过 ...