【赛后补题】ccpc2107秦皇岛H题
来源:互联网 发布:淘宝商品不含区间价格 编辑:程序博客网 时间:2024/05/03 09:50
ZOJ上可以补
赛场上偷听到了隔壁的匈牙利
然后一波操作,未曾想匈牙利之后操作如此复杂
毕竟金牌题,技不如人,甘拜下风
思路: 奇数和偶数分别算作一个集合,二分图构造完毕
烦人的就是那个1,1+1是质数,1+2也是质数,先1内部考虑,然后1+2
(写这段话的时候发现我想错了)
NONONO应该先考虑1+2,再考虑1+1
zoj数据没那么严,不想改了,各位随意
———-吉老师纠正
1+2的在二分图中已经判断了,太好了,我又写了一堆冗余代码,
wtf()
所以剩下的就是,很多很多个1和一堆单身狗们(该说法来自匈牙利算法趣写)
#include <bits/stdc++.h>using namespace std;typedef long long LL;const int N = 3e3 + 7;//-------------------------prime--------------------------------const int PRIME_N = 2e6 + 7;int prime[PRIME_N], primesize;bool isprime[PRIME_N + 7];void getprime(int listsize){ memset(isprime, 1, sizeof(isprime)); isprime[1] = false; primesize = 0; for(int i=2; i < listsize; i++){ if(isprime[i]) prime[++primesize]=i; for(int j = 1; j <= primesize && i*prime[j] < listsize; j++){ isprime[i*prime[j]] = false; if(i%prime[j] == 0) break; } }}//-------------------------hungary-------------------------------bool marry[N], adore[N];int arr[N], boy[N], gir[N], B, G;struct Hungary{ vector <int> G[N]; bool used[N];// main里面记得memset int girl[N], n; inline void init(int _n){ n = _n; for (int i = 0; i <= n; i++) G[i].clear(); } inline void addEdge(const int &u, const int &v){ G[u].push_back(v); } bool Find(int x){ for (int i = 0; i < G[x].size(); i++){ //扫描每个妹子 int j = G[x][i]; if (used[j]) continue; // 如果有暧昧并且还没有标记过 // (这里标记的意思是这次查找曾试图改变过该妹子的归属问题, // 是没有成功,所以就不用瞎费工夫了) used[j] = 1; if (girl[j] == 0 || Find(girl[j])) { //名花无主或者能腾出个位置来,这里使用递归 girl[j] = x; marry[boy[x]] = marry[gir[j]] = true; // this problem return true; } } return false; } inline int hungary(const int &n){ int all = 0; memset(girl, 0, sizeof girl); memset(marry, false, sizeof marry); // this problem for (int i = 1; i <= n; i++) { memset(used, 0, sizeof(used)); //这个在每一步中清空 if (Find(i)) all += 1; } return all; }} hg;inline int wtf(const int &n, const int &B, const int &k){ int mat = hg.hungary(B); //printf("mat = %d\n", mat); if (mat >= k) return k * 2; int cnt1 = 0, idx = n; // number of one for (int i = n; i >= 1; i--){ if (arr[i] != 1) {idx = i; break;} if ((!marry[i])) cnt1++; marry[i] = true; } //printf("cnt1 = %d\n", cnt1); mat += cnt1 >> 1; // 剩下的1 if (mat >= k) return k*2; int left = cnt1 & 1; // 单身狗们 for (int i = 1; i <= idx; i++){ left += (!marry[i]) & adore[i]; } if (mat + left <= k) return mat*2+left; return mat*2 + (k - mat);}int main(){ //freopen("in.txt", "r", stdin); getprime(2e6 + 7); int _; scanf("%d", &_); for (int n, k; _--;) { scanf("%d%d", &n, &k); for (int i = 1; i <= n; i++) scanf("%d", &arr[i]); sort(arr + 1, arr + n+1, greater<int>()); B = G = 0; for (int i = 1; i <= n; i++){ if (arr[i] & 1) boy[++B] = i; else gir[++G] = i; } hg.init(B); memset(adore, false, sizeof adore); for (int i = 1; i <= B; i++){ for (int j = 1; j <= G; j++){ int num = arr[boy[i]] + arr[gir[j]]; if (isprime[num]) { hg.addEdge(i, j); adore[boy[i]] = adore[gir[j]] = true; } } } int ans = wtf(n, B, k); printf("%d\n", ans); } return 0;}
吉老师好帅,,,
网络流跑二分图会快很多,
150ms
#include <bits/stdc++.h>using namespace std;typedef long long LL;const int N = 3e3 + 7;const int INF=0x3f3f3f3f;//-------------------------prime--------------------------------const int PRIME_N = 2e6 + 7;int prime[PRIME_N], primesize;bool isprime[PRIME_N + 7];void getprime(int sz){ memset(isprime, 1, sizeof(isprime)); isprime[1] = false; primesize = 0; for (int i = 2; i < sz; i++){ if (isprime[i]) prime[++primesize]=i; for (int j = 1; j <= primesize && i*prime[j] < sz; j++){ isprime[i*prime[j]] = false; if (i % prime[j] == 0) break; } }}bool marry[N], adore[N];int arr[N], boy[N], gir[N], B, G;//------------------------Dinic-maxFlow--------------------------struct gragh{ struct Edge{ int from, to, cap, flow; Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){} }; int n, s, t; vector <Edge> edges; vector < int> G[N]; //gragh bool vis[N]; //use when bfs int d[N],cur[N];//dist,now edge,use in dfs inline void init(int _n, int _s, int _t){ n = _n; s = _s, t = _t; edges.clear(); for (int i = 0; i <= n; i++) G[i].clear(); } inline void addEdge(int from, int to, int cap){ edges.push_back(Edge(from,to,cap,0)); edges.push_back(Edge(to,from, 0 ,0)); int top = edges.size(); G[from].push_back(top-2); G[ to ].push_back(top-1); } inline bool BFS(){ memset(vis, 0, sizeof(vis)); queue <int> Q; d[s]=0;vis[s]=1; for (Q.push(s); !Q.empty();){ int x = Q.front(); Q.pop(); for (int i = 0; i < G[x].size(); i++){ Edge &e = edges[G[x][i]]; if (vis[e.to] || e.cap <= e.flow)continue; vis[e.to] = 1; d[e.to] = d[x] + 1; Q.push(e.to); } } return vis[t]; } inline int DFS(const int& x,int a){ //printf("dfs:%d,%d\n",x,a); if (x==t||a==0){return a;} int flow = 0, f; for (int& i = cur[x]; i < G[x].size(); i++){ Edge& e = edges[G[x][i]]; if (d[x] + 1 != d[e.to]) continue; if ((f=DFS(e.to,min(a,e.cap-e.flow)))<=0)continue; e.flow += f; edges[G[x][i]^1].flow -= f;//反向边 flow+=f; a-=f; marry[x] = marry[e.to] = true; if (a==0) break; } return flow; } inline int maxFlow(){return maxFlow(s,t);} inline int maxFlow(const int& s, const int& t){ //if (edges.size() > N*N>>1) return 233; int flow = 0; while (BFS()){ memset(cur, 0, sizeof(cur)); int f = DFS(s, INF); flow += f ; } return flow; }} g;inline int wtf(const int &n, const int &B, const int &k){ memset(marry, false, sizeof marry); int mat = g.maxFlow(); //printf("mat = %d\n", mat); if (mat >= k) return k * 2; int cnt1 = 0, idx = n; // number of one for (int i = n; i >= 1; i--){ if (arr[i] != 1) {idx = i; break;} if ((!marry[i])) cnt1++; marry[i] = true; } //printf("cnt1 = %d\n", cnt1); mat += cnt1 >> 1; // 剩下的1 if (mat >= k) return k*2; int left = cnt1 & 1; // 单身狗们 for (int i = 1; i <= idx; i++){ left += (!marry[i]) & adore[i]; } if (mat + left <= k) return mat*2+left; return mat*2 + (k - mat);}int main(){ //freopen("in.txt", "r", stdin); getprime(2e6 + 7); int _; scanf("%d", &_); for (int n, k; _--;) { scanf("%d%d", &n, &k); for (int i = 1; i <= n; i++) scanf("%d", &arr[i]); sort(arr + 1, arr + n + 1, greater<int>()); B = G = 0; g.init(n + 1, 0, n + 1); for (int i = 1; i <= n; i++){ if (arr[i] & 1) { boy[++B] = i; g.addEdge(0, i, 1); } else { gir[++G] = i; g.addEdge(i, n+1, 1); } } memset(adore, false, sizeof adore); for (int i = 1; i <= B; i++){ for (int j = 1; j <= G; j++){ int num = arr[boy[i]] + arr[gir[j]]; if (isprime[num]) { g.addEdge(boy[i], gir[j], 1); adore[boy[i]] = adore[gir[j]] = true; } } } int ans = wtf(n, B, k); printf("%d\n", ans); } return 0;}
真的是佛了
匈牙利过了,拿前向星版的dinic死活re和wa,找了一年前的vector的dinic板子直接过了,一行一行对,没办法,拿vector的板子现场该前向星,还是狂wa
没错,下面这段代码wa到死,睿智了
#include <bits/stdc++.h>using namespace std;typedef long long LL;const int N = 3e3 + 7;const int INF = 0x3f3f3f3f;//-------------------------prime--------------------------------const int PRIME_N = 2e6 + 7;int prime[PRIME_N], primesize;bool isprime[PRIME_N + 7];void getprime(int listsize){ memset(isprime, 1, sizeof(isprime)); isprime[1] = false; primesize = 0; for (int i = 2; i < listsize; i++){ if (isprime[i]) prime[++primesize]=i; for (int j = 1; j <= primesize && i*prime[j] < listsize; j++){ isprime[i*prime[j]] = false; if (i % prime[j] == 0) break; } }}bool marry[N], adore[N];int arr[N], boy[N], gir[N], B, G;//------------------------Dinic-maxFlow--------------------------struct Dinic{ struct Edge{ int from, to, cap, flow, nxt; Edge(){} Edge(int u,int v,int c,int f, int n):from(u),to(v),cap(c),flow(f),nxt(n){} } edges[N*N>>1]; int n, s, t, E, head[N]; bool vis[N]; //use when bfs int d[N], cur[N]; //dist, now edge, use in dfs inline void init(int _n, int _s, int _t){ n = _n; s = _s, t = _t; E = 0; for (int i = 0; i <= n; i++) head[i] = -1; } inline void addEdge(int f, int t, int c){ edges[E] = Edge(f, t, c, 0, head[f]); head[f] = E++; edges[E] = Edge(t, f, 0, 0, head[t]); head[t] = E++; } inline bool BFS(){ memset(vis, 0, sizeof(vis)); queue <int> Q; d[s] = 0; vis[s] = 1; for (Q.push(s); !Q.empty();){ int x = Q.front(); Q.pop(); for (int i = head[x]; ~i; i = edges[i].nxt){ Edge &e = edges[i]; if (vis[e.to] || e.cap <= e.flow) continue; vis[e.to] = 1; d[e.to] = d[x] + 1; Q.push(e.to); } } return vis[t]; } inline int DFS(const int& x, int a){ //printf("dfs:%d,%d\n",x,a); if (x == t || a == 0) return a; int flow = 0, f; for (int& i = cur[x]; ~i; i = edges[i].nxt){ Edge& e = edges[i]; if (d[x] + 1 != d[e.to]) continue; if ((f = DFS(e.to,min(a,e.cap-e.flow))) <= 0)continue; e.flow += f; edges[i^1].flow-=f;//反向边 flow+=f; a-=f; marry[x] = marry[e.to] = true; if (a==0) break; } return flow; } inline int maxFlow(){return maxFlow(s,t);} inline int maxFlow(const int& s, const int& t){ int flow = 0; while (BFS()){ for (int i = 0; i <= n; i++) cur[i] = head[i]; int f = DFS(s, INF); flow += f ; } return flow; }} g;inline int wtf(const int &n, const int &B, const int &k){ memset(marry, false, sizeof marry); int mat = g.maxFlow(); //printf("mat = %d\n", mat); if (mat >= k) return k * 2; int cnt1 = 0, idx = n; // number of one for (int i = n; i >= 1; i--){ if (arr[i] != 1) {idx = i; break;} if ((!marry[i])) cnt1++; marry[i] = true; } //printf("cnt1 = %d\n", cnt1); mat += cnt1 >> 1; // 剩下的1 if (mat >= k) return k*2; int left = cnt1 & 1; // 单身狗们 for (int i = 1; i <= idx; i++){ left += (!marry[i]) & adore[i]; } if (mat + left <= k) return mat*2+left; return mat*2 + (k - mat);}int main(){ //freopen("in.txt", "r", stdin); getprime(2e6 + 7); int _; scanf("%d", &_); for (int n, k; _--;) { scanf("%d%d", &n, &k); for (int i = 1; i <= n; i++) scanf("%d", &arr[i]); sort(arr + 1, arr + n + 1, greater<int>()); B = G = 0; g.init(n + 1, 0, n + 1); for (int i = 1; i <= n; i++){ if (arr[i] & 1) { boy[++B] = i; g.addEdge(0, i, 1); } else { gir[++G] = i; g.addEdge(i, n+1, 1); } } memset(adore, false, sizeof adore); for (int i = 1; i <= B; i++){ for (int j = 1; j <= G; j++){ int num = arr[boy[i]] + arr[gir[j]]; if (isprime[num]) { g.addEdge(boy[i], gir[j], 1); adore[boy[i]] = adore[gir[j]] = true; } } } int ans = wtf(n, B, k); printf("%d\n", ans); } return 0;}
阅读全文
0 0
- 【赛后补题】ccpc2107秦皇岛H题
- 国庆4&5赛后补题
- 赛后补题 POJ 3182 bfs变形
- gdufs新手赛赛后补题
- Codeforces Round #207 (Div. 2) 赛后补题
- Codeforces Round #208 (Div. 2) 赛后补题
- Codeforces Round #209 (Div. 2)赛后补题
- 【赛后补题】(HDU6228) Tree {2017-ACM/ICPC Shenyang Onsite}
- H补题
- 【赛后补题】(HDU6223) Infinite Fraction Path {2017-ACM/ICPC Shenyang Onsite}
- 2017 CCPC 秦皇岛 G题
- 2017 CCPC 秦皇岛 G题
- ZOJ3981 CCPC秦皇岛站A题
- 2017 ACM Amman Collegiate Programming Contest-补题-H
- GDKOI2016赛后总结(比赛做题策略)
- ZOJ 3988(ccpc秦皇岛H)
- CCPC.2017秦皇岛站 H-prime set
- 补题
- http协议学习-全面理解HTTP
- MFC 使用CFileDialog打开多个文件
- git add -A和 git add . git add -u作用和区别
- oracle中的nvl函数讲解
- Kafka设计解析(六)- Kafka高性能架构之道
- 【赛后补题】ccpc2107秦皇岛H题
- 由IO流关闭引发的关于垃圾回收机制及finalize()的理解
- IMU误差研究
- 水平线与垂直线提取
- tensorflow中RNNcell源码分析以及自定义RNNCell的方法
- 十月份新知识点总结
- java 根据excel模板格式导出指定格式的excel
- vue-cli#2.0 webpack 配置分析
- 虚拟机(VMware)之在Ubuntu下安装VMware Tools