EOJ月赛:唐纳德和他的数学老师(二分图匹配 & 最大流)
来源:互联网 发布:频率发生器软件 编辑:程序博客网 时间:2024/06/05 06:36
Time limit per test: 1.0 seconds
Memory limit: 256 megabytes
唐纳德是一个数学天才。有一天,他的数学老师决定为难一下他。他跟唐纳德说:「现在我们来玩一个游戏。这个游戏总共
因为数学老师是刻意为难,所以这个游戏很有可能不可能进行到最后。但是聪明的数学老师早就已经知道这个游戏最多能进行几轮了。现在他把问题抛给了你,想看看你知不知道。
注意,
Input
输入具有如下形式:
第一行一个整数
第二行
Output
输出游戏最多能进行几轮。
Examples
input
37 6 3
output
3
input
52 2 2 2 2
output
1
Source
EOJ Monthly 2017.12
①最大匹配每处理一个数,就将它和它的质因子建边,然后跑一次匈牙利看是否增多了一条边即可。
②二分答案+最大流,对每个质因子拆点(不拆也可以^_^),建容量为1的边,源点--第某轮--某轮的质因子--某论的质因子副本--汇点。
# include <iostream># include <cstdio># include <cstring># include <vector># include <algorithm># define mp make_pair# define pb push_backusing namespace std;typedef long long LL;const int maxn = 1e6+30;int a[3003], l[maxn];vector<int>v[3003], g[3003];bool vis[maxn];bool dfs(int u){ for(int i=0; i<g[u].size(); ++i) { int j = g[u][i]; if(!vis[j]) { vis[j] = true; if(l[j] == -1 || dfs(l[j])) { l[j] = u; return true; } } } return false;}int main(){ int n, ans; scanf("%d",&n); memset(l, -1, sizeof(l)); for(int i=1; i<=n; ++i) { scanf("%d",&a[i]); if(a[i] == 1) { n = i-1; break; } for(int j=2; j*j<=a[i]; ++j) { while(a[i]%j==0) { v[i].pb(j); a[i]/=j; } } if(a[i]!=1) v[i].pb(a[i]); } if(n==0) return 0*puts("0"); for(int i=1; i<=n; ++i) { for(int j=0; j<v[i].size(); ++j) g[i].pb(v[i][j]); memset(vis, false, sizeof(vis)); if(!dfs(i)) break; else ans=i; } printf("%d\n",ans); return 0;}
# include <iostream># include <cstdio># include <cstring># include <vector># include <algorithm># define mp make_pair# define pb push_backusing namespace std;typedef long long LL;const int maxn = 1e6+3003;int a[3003];vector<int>v[3003];struct node{ int v, w, next;}edge[maxn<<2];int n, cnt, Next[maxn*2], len=1e6;int dis[maxn*2], source, sink, q[maxn<<2];int vis[maxn*2];void add(int u, int v, int w){ edge[cnt] = {v,w,Next[u]}; Next[u] = cnt++; edge[cnt] = {u,0,Next[v]}; Next[v] = cnt++;}bool bfs(){ memset(dis, -1, sizeof(dis)); dis[source] = 0; int l=0, r=0; q[r++] = source; while(l<r) { int u = q[l]; ++l; for(int i=Next[u]; i!=-1; i=edge[i].next) { int v = edge[i].v, w=edge[i].w; if(w>0 && dis[v]==-1) { dis[v] = dis[u]+1; q[r++] = v; } } } return dis[sink] != -1;}int dfs(int u, int pre){ if(u == sink) return pre; int ans = 0, f = 0; for(int i=Next[u]; i!=-1; i=edge[i].next) { int v = edge[i].v, w=edge[i].w; if(dis[v] == dis[u]+1 && w>0 && (f=dfs(v, min(w, pre)))) { edge[i].w -= f; edge[i^1].w += f; pre -= f; ans += f; if(!pre) break; } } if(ans) return ans; dis[u] = -1; return 0;}bool check(int x){ cnt = 0; source=0, sink=2e6+n; memset(vis, 0, sizeof(vis)); memset(Next, -1, sizeof(Next)); for(int i=1; i<=x; ++i) { add(0, i, 1); for(int j=0; j<v[i].size(); ++j) { int k=v[i][j]; if(++vis[k]==1) { add(k+n, k+n+len, 1); add(k+n+len, sink, 1); } add(i, k+n, 1); } } int max_flow=0; while(bfs()) max_flow += dfs(source, 0x3f3f3f3f); return max_flow == x;}int main(){ scanf("%d",&n); for(int i=1; i<=n; ++i) { scanf("%d",&a[i]); if(a[i] == 1) { n = i-1; break; } for(int j=2; j*j<=a[i]; ++j) { while(a[i]%j==0) { v[i].pb(j); a[i]/=j; } } if(a[i]!=1) v[i].pb(a[i]); } if(n==0) return 0*puts("0"); int l=1,r=n; while(l<=r) { int mid = l+r>>1; if(check(mid)) l=mid+1; else r=mid-1; } printf("%d\n",r); return 0;}
阅读全文
1 0
- EOJ月赛:唐纳德和他的数学老师(二分图匹配 & 最大流)
- EOJ Monthly 2017.12 题解 3449. 唐纳德和他的数学老师
- EOJ 2069 Asteroids 二分图最大匹配
- 二分图最大匹配和网络最大流的转换
- EOJ 1864 二分图匹配
- (substr strstr 的学习) EOJ Monthly 2017.12 (暨 ECNU 12 月内部选拔) G1. 唐纳德与子串 (Easy)
- EOJ Monthly 2017.12 (暨 ECNU 12 月内部选拔) A. 唐纳德先生和假骰子
- EOJ 3452- 唐纳德先生和假骰子
- EOJ 3452 唐纳德先生和假骰子
- 最大流和二分匹配
- 二分图和最大匹配
- 二分图的判断和二分图最大匹配模板
- 二分图的最大匹配、完美匹配和匈牙利算法
- 二分图的最大匹配、完美匹配和匈牙利算法
- 二分图的最大匹配、完美匹配和匈牙利算法
- 二分图的最大匹配、完美匹配和匈牙利算法
- 二分图的最大匹配、完美匹配和匈牙利算法
- 二分图的最大匹配、完美匹配和匈牙利算法
- C/C++中system()函数详解
- 编排工具对于Linux的优化之道
- [Ynoi2017]舌尖上的由乃
- Python学习笔记----面向对象
- 12.2作业
- EOJ月赛:唐纳德和他的数学老师(二分图匹配 & 最大流)
- 空格替换
- 583.Delete Operation for Two Strings
- CSS(十九)
- [USACO5.3]校园网Network of Schools Tarjan缩点
- 視覺相關
- Python实现Pat 1035. Password (20)
- springmvc-validate数据验证
- leetcode 447. Number of Boomerangs