bzoj4205 卡牌配对
来源:互联网 发布:linux 输出日志命令 编辑:程序博客网 时间:2024/05/20 06:23
卡牌配对
题目背景:
bzoj4205
分析:我相信很多人第一反应都是暴力连边然后暴力二分图匹配,然后我的常数还没有小到n2过30000,所以我们来想想该怎么办,考虑到200以内的质数只有46个,我们可以选择增加3 * 46 * 46个点,将左边的某种属性有第i个质因数,另一个属性有第j个质因数的点连向对应的一个点,并将这个点与右边满足上述条件的点相连,然后新建源点汇点就可以跑最大流了,大概是一个70000个点,2000000条边的网络流(200以内的数最多3个质因数,所以最多不超过27条边),他竟然让大胆玩高渐进复杂度,那当然就直接上吧。
Source:
/* created by scarlyw*/#include <cstdio>#include <string>#include <algorithm>#include <cstring>#include <iostream>#include <cmath>#include <cctype>#include <vector>#include <set>#include <queue> inline char read() { static const int IN_LEN = 1024 * 1024; static char buf[IN_LEN], *s, *t; if (s == t) { t = (s = buf) + fread(buf, 1, IN_LEN, stdin); if (s == t) return -1; } return *s++;} ///*template<class T>inline void R(T &x) { static char c; static bool iosig; for (c = read(), iosig = false; !isdigit(c); c = read()) { if (c == -1) return ; if (c == '-') iosig = true; } for (x = 0; isdigit(c); c = read()) x = ((x << 2) + x << 1) + (c ^ '0'); if (iosig) x = -x;}//*/ const int OUT_LEN = 1024 * 1024;char obuf[OUT_LEN], *oh = obuf;inline void write_char(char c) { if (oh == obuf + OUT_LEN) fwrite(obuf, 1, OUT_LEN, stdout), oh = obuf; *oh++ = c;} template<class T>inline void W(T x) { static int buf[30], cnt; if (x == 0) write_char('0'); else { if (x < 0) write_char('-'), x = -x; for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 + 48; while (cnt) write_char(buf[cnt--]); }} inline void flush() { fwrite(obuf, 1, oh - obuf, stdout);} /*template<class T>inline void R(T &x) { static char c; static bool iosig; for (c = getchar(), iosig = false; !isdigit(c); c = getchar()) if (c == '-') iosig = true; for (x = 0; isdigit(c); c = getchar()) x = ((x << 2) + x << 1) + (c ^ '0'); if (iosig) x = -x;}//*/ const int MAXN = 70000 + 10;const int MAXX = 200 + 5;const int prime[50] = {0, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199}; struct node { int to, w, rev; node(int to = 0, int w = 0, int rev = 0) : to(to), w(w), rev(rev) {}} ; struct data { int a, b, c;} x[MAXN], y[MAXN]; std::vector<node> edge[MAXN]; int n1, n2, n, s, t;int id[3][MAXX][MAXX], dis[MAXN], gap[MAXN]; inline void add_edge(int x, int y, int w) { edge[x].push_back(node(y, w, edge[y].size())); edge[y].push_back(node(x, 0, edge[x].size() - 1));} inline void read_in() { R(n1), R(n2); for (int i = 1; i <= n1; ++i) R(x[i].a), R(x[i].b), R(x[i].c); for (int i = 1; i <= n2; ++i) R(y[i].a), R(y[i].b), R(y[i].c);} inline int solve(int n, int *a) { int top = 0; for (int i = 2; i <= sqrt(n); ++i) { if (n % i == 0) a[++top] = i; while (n % i == 0) n /= i; } if (n != 1) a[++top] = n; return top;} inline void build_graph() { n = n1 + n2; for (int i = 0; i < 3; ++i) for (int j = 1; j <= 46; ++j) for (int k = 1; k <= 46; ++k) id[i][prime[j]][prime[k]] = ++n; s = ++n, t = ++n; int a[MAXX], b[MAXX], c[MAXX]; for (int i = 1; i <= n1; ++i) { add_edge(s, i, 1); int top1 = solve(x[i].a, a); int top2 = solve(x[i].b, b); int top3 = solve(x[i].c, c); for (int k1 = 1; k1 <= top1; ++k1) for (int k2 = 1; k2 <= top2; ++k2) add_edge(i, id[0][a[k1]][b[k2]], 1); for (int k1 = 1; k1 <= top1; ++k1) for (int k3 = 1; k3 <= top3; ++k3) add_edge(i, id[1][a[k1]][c[k3]], 1); for (int k2 = 1; k2 <= top2; ++k2) for (int k3 = 1; k3 <= top3; ++k3) add_edge(i, id[2][b[k2]][c[k3]], 1); } for (int i = 1; i <= n2; ++i) { add_edge(i + n1, t, 1); int top1 = solve(y[i].a, a); int top2 = solve(y[i].b, b); int top3 = solve(y[i].c, c); for (int k1 = 1; k1 <= top1; ++k1) for (int k2 = 1; k2 <= top2; ++k2) add_edge(id[0][a[k1]][b[k2]], n1 + i, 1); for (int k1 = 1; k1 <= top1; ++k1) for (int k3 = 1; k3 <= top3; ++k3) add_edge(id[1][a[k1]][c[k3]], n1 + i, 1); for (int k2 = 1; k2 <= top2; ++k2) for (int k3 = 1; k3 <= top3; ++k3) add_edge(id[2][b[k2]][c[k3]], n1 + i, 1); }} ///*inline int sap(int cur, int flow, int s, int t, int n) { if (cur == t) return flow; int del = 0; static int temp[MAXN]; for (int p = temp[cur]; p < edge[cur].size(); ++p) { node *e = &edge[cur][p]; if (e->w > 0 && dis[e->to] + 1 == dis[cur]) { int ret = sap(e->to, std::min(flow - del, e->w), s, t, n); e->w -= ret, edge[e->to][e->rev].w += ret, temp[cur] = p; if ((del += ret) == flow || dis[cur] >= n) return temp[cur] = 0, del; } } if (--gap[dis[cur]] == 0) dis[s] = n; return gap[++dis[cur]]++, temp[cur] = 0, del;} inline int sap(int s, int t, int n) { int ret = 0; for (gap[0] = n; dis[s] < n; ) ret += sap(s, ~0u >> 1, s, t, n); return ret;}//*/int main() { read_in(); build_graph(); std::cout << sap(s, t, n); return 0;}
阅读全文
0 0
- BZOJ4205卡牌配对
- bzoj4205: 卡牌配对
- BZOJ4205: 卡牌配对
- Bzoj4205卡牌配对
- bzoj4205 卡牌配对
- bzoj4205 卡牌配对
- bzoj4205[FJ2015集训] 卡牌配对
- BZOJ 4205: 卡牌配对
- BZOJ P4205[FJ2015集训]卡牌配对
- 配对
- 配对
- BZOJ-4205 卡牌配对 最大流+线性筛+神建模
- 机顶盒机卡配对操作教程
- 生肖配对
- 括号配对
- 括号配对
- 蓝牙配对
- 【贪心】配对
- abap table control控制光标
- git使用(一):常见的git命令
- 使用OpenSSL实现CA证书的搭建过程
- 传统应用层逻辑分库DB迁移阿里云DRDS+RDS分布式数据库
- Axure学习之滑动条
- bzoj4205 卡牌配对
- php.ini修改php上传文件大小限制的方法详解
- 七成消费者可持续消费意识强 中企动力全网门户助中小企业可劲儿圈粉
- 操作系统--进程概念及其调度
- 170920_Spring英文文档阅读(十二)_2.3 Usage scenarios(四)
- H.264 宏块级RDO控制
- opencv开发笔记(八):利用感兴趣区域ROI实现图像叠加
- webstorm 2017 激活破解
- IT连创业系列:创业者逆境下的思维