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 ...
随机推荐
- JQ的表单验证
(function () { $("#but").click(function () { if ($("#name").val() == "" ...
- iscroll5实现一个下拉刷新上拉加载的效果
直接上代码!!! <!DOCTYPE html><html><head lang="en"> <meta charset="UT ...
- linux 环境下运行STS时 出现must be available in order to run STS
linux 环境下运行ECLIPSE时 出现 “ A Java Runtime Environment (JRE) or Java Development Kit (JDK) must be avai ...
- Java 性能分析工具 , 第 1 部分: 操作系统工具
引言 性能分析的前提是将应用程序内部的运行状况以及应用运行环境的状况以一种可视化的方式更加直接的展现出来,如何来达到这种可视化的展示呢?我们需要配合使用操作系统中集成的程序监控工具和 Java 中内置 ...
- MySQL多实例安装
1.安装MySQL需要的依赖的包和编译软件 (1)安装MySQL需要的依赖包 安装MySQL之前,最好先安装MySQL需要的依赖包,不然后面会出现报错,还得回来安装MySQL的依赖包. [root ...
- chrome中不可见字符引发的float问题
起因是刷知乎时碰到这么个问题:https://www.zhihu.com/question/41400503 问题代码如下: <!DOCTYPE html> <html lang=& ...
- Ubuntu16.04 LTS下apt安装WireShark
Ubuntu16.04 LTS下apt安装WireShark 安装与配置 首先通过apt安装WireShark: $ sudo apt install wireshark 会同时安装许多的依赖包,其中 ...
- kettle中含有参数传递的定时任务
(1)新建一个作业(新建->作业),并在控制面板右键: (2)设置一个命令参数: (3)把作业的参数传递给转换: (4)在转换中右键设置转换属性: (5)接收作业中设置的传递参数: (6)参数的 ...
- 什么时候用IntentService
IntentService是继承自Service类的,在执行耗时操作时,其实,只需要在service中的onStartCommand(主线程)新启一个线程即可,那IntentService什么时候用来 ...
- win7下安装配置nodejs、使用npm安装express
1.下载node http://nodejs.cn/download/ 这里下载自己需要的 我的环境是win764,下载地址是:https://nodejs.org/dist/v6.2.0/win-x ...