BZOJ 4205: 卡牌配对
4205: 卡牌配对
Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 173 Solved: 76
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
2 2 2
2 5 5
2 2 5
5 5 5
Sample Output
【提示】
样例中第一张X类卡牌和第一张Y类卡牌能配对,第二张X类卡牌和两张Y类卡牌都能配对。所以最佳方案是第一张X和第一张Y配对,第二张X和第二张Y配对。
另外,请大胆使用渐进复杂度较高的算法!
HINT
Source
看到之后显然有个暴力建二分图,求最大匹配的想法,但显然N^2的复杂度难以接受,而最大匹配也是极慢的。
所以考虑在左右部点中间设立一些中转站,目的是将边按照一定的规律归并,减少复杂度。
因为至多只能有一组数互质,所以至少有两组数GCD不为1,每对数均含有至少一个相同的质因子。
而200以内的质因子只有46个,所以可以枚举第一、二组含有的相同质因子,以及这两组是AB,BC,还是CA。
所以中转站的个数为46*46*3;又因为200以内的数至多含有4个质因子,所以边数也是有保证的。
建图之后跑最大流即可,貌似需要一些优化,看自己的常数了,拼脸也可以。
#include <cstdio>
#include <cstring> inline int nextChar(void) {
const int siz = ;
static char buf[siz];
static char *hd = buf + siz;
static char *tl = buf + siz;
if (hd == tl)
fread(hd = buf, , siz, stdin);
return int(*hd++);
} inline int nextInt(void) {
register int ret = ;
register int neg = false;
register int bit = nextChar();
for (; bit < ; bit = nextChar())
if (bit == '-')neg ^= true;
for (; bit > ; bit = nextChar())
ret = ret * + bit - ;
return neg ? -ret : ret;
} const int pri[] = {
, , , , , , , , , , , , , ,
, , , , , , , , , , , , ,
, , , , , , , , , , ,
, , , , , , , ,
}; const int inf = 1e9;
const int siz = ; int s, t;
int edges;
int hd[siz];
int to[siz];
int nt[siz];
int fl[siz]; inline void add(int u, int v, int f) {
// printf("%d %d %d\n", u, v, f);
nt[edges] = hd[u]; to[edges] = v; fl[edges] = f; hd[u] = edges++;
nt[edges] = hd[v]; to[edges] = u; fl[edges] = ; hd[v] = edges++;
} int dep[]; inline bool bfs(void) {
static int que[siz], head, tail;
memset(dep, , sizeof(dep));
dep[que[head = ] = s] = tail = ;
while (head != tail) {
int u = que[head++], v;
for (int i = hd[u]; ~i; i = nt[i])
if (fl[i] && !dep[v = to[i]])
dep[que[tail++] = v] = dep[u] + ;
}
return dep[t];
} int lst[]; int dfs(int u, int f) {
if (u == t || !f)return f;
int used = , flow, v;
for (int i = lst[u]; ~i; i = nt[i])
if (dep[v = to[i]] == dep[u] + ) {
flow = dfs(v, f - used < fl[i] ? f - used : fl[i]);
used += flow;
fl[i] -= flow;
fl[i^] += flow;
if (fl[i])lst[u] = i;
if (used == f)return f;
}
if (!used)dep[u] = ;
return used;
}; inline int maxFlow(void) {
int maxFlow = , newFlow;
while (bfs()) {
for (int i = s; i <= t; ++i)
lst[i] = hd[i];
while (newFlow = dfs(s, inf))
maxFlow += newFlow;
}
return maxFlow;
} int n, m; int fac[][]; int map[][][]; signed main(void) {
n = nextInt();
m = nextInt();
for (int i = ; i <= ; ++i)
for (int j = ; j <= ; ++j)
if (i % pri[j] == )
fac[i][++fac[i][]] = j;
for (int i = , c = n + m; i < ; ++i)
for (int j = ; j <= ; ++j)
for (int k = ; k <= ; ++k)
map[i][j][k] = ++c;
memset(hd, -, sizeof(hd));
s = , t = n + m + ** + ;
for (int i = ; i <= n; ++i) {
add(s, i, );
int a = nextInt();
int b = nextInt();
int c = nextInt();
for (int j = ; j <= fac[a][]; ++j)
for (int k = ; k <= fac[b][]; ++k)
add(i, map[][fac[a][j]][fac[b][k]], );
for (int j = ; j <= fac[b][]; ++j)
for (int k = ; k <= fac[c][]; ++k)
add(i, map[][fac[b][j]][fac[c][k]], );
for (int j = ; j <= fac[c][]; ++j)
for (int k = ; k <= fac[a][]; ++k)
add(i, map[][fac[c][j]][fac[a][k]], );
}
for (int i = ; i <= m; ++i) {
add(i + n, t, );
int a = nextInt();
int b = nextInt();
int c = nextInt();
for (int j = ; j <= fac[a][]; ++j)
for (int k = ; k <= fac[b][]; ++k)
add(map[][fac[a][j]][fac[b][k]], i + n, );
for (int j = ; j <= fac[b][]; ++j)
for (int k = ; k <= fac[c][]; ++k)
add(map[][fac[b][j]][fac[c][k]], i + n, );
for (int j = ; j <= fac[c][]; ++j)
for (int k = ; k <= fac[a][]; ++k)
add(map[][fac[c][j]][fac[a][k]], i + n, );
}
printf("%d\n", maxFlow());
}
@Author: YouSiki
BZOJ 4205: 卡牌配对的更多相关文章
- 【BZOJ4205】卡牌配对
Description 现在有一种卡牌游戏,每张卡牌上有三个属性值:A,B,C.把卡牌分为X,Y两类,分别有n1,n2张. 两张卡牌能够配对,当且仅当,存在至多一项属性值使得两张卡牌该项属性值互质,且 ...
- 【BZOJ4205】卡牌配对 最大流
[BZOJ4205]卡牌配对 Description 现在有一种卡牌游戏,每张卡牌上有三个属性值:A,B,C.把卡牌分为X,Y两类,分别有n1,n2张. 两张卡牌能够配对,当且仅当,存在至多一项属性值 ...
- [BZOJ4205][FJ2015集训]卡牌配对
题目:卡牌配对 传送门:None 题目大意:有$n_1$张$X$类牌和$n_2$张$Y$类类牌,每张卡牌上有三个属性值:$A,B,C$.两张卡牌能够配对,当且仅当,存在至多一项属性值使得两张卡牌该项属 ...
- [BZOJ4205][FJ2015集训] 卡牌配对 [建图+最大流]
题面 这是bzoj权限题,题面可以去下面的离线题库找 离线4205,只有题面,不能提交 思路 二分图匹配 这道题模型显然就是个二分图匹配嘛 那我们两两判断一下然后连边匹配.....就只有30分了 因为 ...
- BZOJ4205卡牌配对——最大流+建图优化
题目描述 现在有一种卡牌游戏,每张卡牌上有三个属性值:A,B,C.把卡牌分为X,Y两类,分别有n1,n2张. 两张卡牌能够配对,当且仅当,存在至多一项属性值使得两张卡牌该项属性值互质,且两张卡牌类别不 ...
- 刷题总结——卡牌配对(bzoj4205网络流)
题目: Description 现在有一种卡牌游戏,每张卡牌上有三个属性值:A,B,C.把卡牌分为X,Y两类,分别有n1,n2张. 两张卡牌能够配对,当且仅当,存在至多一项属性值使得两张卡牌该项属性值 ...
- BZOJ4205 : 卡牌配对
对于两张卡牌,如果存在两种属性值不互质,则可以匹配. 只考虑200以内的质数,一共有46个,可以新建3*46*46个点来表示一类属性值中有这两种质数的卡牌. 然后对于每张卡牌,枚举它的质因子,最多只有 ...
- BZOJ 4392 卡牌游戏
Description 奶牛贝茜是卡牌游戏的狂热爱好者, 但是令人吃惊的, 她缺乏对手. 不幸的是, 任何牧 群里的其他牛都不是好对手. 他们实在是太差了 , 实际上, 他们玩卡牌游戏时会遵循一种完全 ...
- bzoj 3191: [JLOI2013]卡牌游戏
Description N个人坐成一圈玩游戏.一开始我们把所有玩家按顺时针从1到N编号.首先第一回合是玩家1作为庄家.每个回合庄家都会随机(即按相等的概率)从卡牌堆里选择一张卡片,假设卡片上的数字为X ...
随机推荐
- 《连载 | 物联网框架ServerSuperIO教程》- 3.设备驱动介绍
1.C#跨平台物联网通讯框架ServerSuperIO(SSIO)介绍 <连载 | 物联网框架ServerSuperIO教程>1.4种通讯模式机制. <连载 | 物联网框架Serve ...
- 深入理解javascript选择器API系列第一篇——4种元素选择器
× 目录 [1]id属性 [2]标签名 [3]name属性[4]all 前面的话 说到最常见的DOM应用,恐怕就要数取得特定的某个或某组元素的引用了.DOM定义了许多方式来选取元素,包括getElem ...
- YYStock开源----iOS股票K线绘制第二版
新的股票绘制粗来啦,欢迎围观star的说(*^__^*) 嘻嘻-- 捏合功能也准备完善了 Github:https://github.com/yate1996/YYStock 长按分时图+五档图 分时 ...
- Service是什么?Service又不是什么?
在Android王国中,Service是一个劳动模范,总是默默的在后台运行,无怨无悔,且总是干最脏最累的活,比如下载文件,倾听音乐,网络操作等这些耗时的操作,所以我们请尊重的叫他一声:"劳模 ...
- 教你怎么半天搞定Docker
首先,不要把docker想的那么高大,它不就是先做个镜像,然后通过docker像虚拟机一样跑起来嘛...docker其实在真实业务场景中还是非常有局限性的.Dockerfile脚本也没那么好写,有些应 ...
- 企业号微信支付 公众号支付 H5调起支付API示例代码 JSSDK C# .NET
先看效果 1.本文演示的是微信[企业号]的H5页面微信支付 2.本项目基于开源微信框架WeiXinMPSDK开发:https://github.com/JeffreySu/WeiXinMPSDK 感谢 ...
- Windows Server 2012 虚拟化实战:存储(二)
五.搭建Window Server 2012虚拟化的存储网络 前文我们讨论了Window Server 2012支持的各种与存储相关的技术,接下来我们通过实践对其中的一些技术进行检验.实际上Windo ...
- Java基础知识笔记(八:集合类)
目录 1 集合类简介 2 List介绍及简单使用 2.1 LinkedList介绍及简单使用 2.2 ArrayList介绍及简单使用 2.3 Vector介绍及简单使用 2.3.1 S ...
- Android 更改 Toast 的默认位置
Android中Toast的默认位置在屏幕靠近底部的位置,这个默认位置有时候并不合适.比如页面上内容较少时,内容一般集中在屏幕上半部分,用户的注意力也集中在屏幕上半部分,默认位置的Toast用户可能没 ...
- C#基础---Attribute(标签) 和 reflect(反射) 应用二
以前我有写过一篇有关,打标签和反射的应用,主要用于类中字段的验证.下面是连接 C#基础---Attribute(标签) 和 reflect(反射) 应用. 这个项目迭代发现公司项目里面发现老代码对业务 ...