D唐纳德和他的数学老师(华师网络赛)(二分匹配,最大流)
Time limit per test: 1.0 seconds
Memory limit: 256 megabytes
唐纳德是一个数学天才。有一天,他的数学老师决定为难一下他。他跟唐纳德说:「现在我们来玩一个游戏。这个游戏总共 n轮,每一轮我都会给你一个数(第 i 轮给出的数是 ai)。你每次要回答一个数,是我给出的这个数的质因数,并且你说出的数不能重复。」
因为数学老师是刻意为难,所以这个游戏很有可能不可能进行到最后。但是聪明的数学老师早就已经知道这个游戏最多能进行几轮了。现在他把问题抛给了你,想看看你知不知道。
注意,1 不是质数。
Input
输入具有如下形式:
na1 a2 … an
第一行一个整数 n (1≤n≤3 000)。
第二行 n 个整数用空格隔开,a1,a2,…,an (2≤ai≤106)。
Output
输出游戏最多能进行几轮。
Examples
input
3 7 6 3
output
3
input
5 2 2 2 2 2
output
1
题意:
现在有一群数字,按顺序给出,对于每一个数字,回答一个素数因子,这次回答的素数因子下次不能再用,如果没有可以回答的素数因子,游戏结束。问游戏最多进行几轮。
思路:
1,匈牙利二分匹配是可以一个一个的加,满足顺序性。
2,网络流算法具有无序性,所以可以二分加最大流。
注意:
尽量少使用memset。这里代码用了时间戳,即代码里的“fa”。
#include<cstdio> #include<cstdlib> #include<iostream> #include<cstring> using namespace std; const int maxn=1000010; const int maxm=2000010; int p[maxn],b[80000],c[maxn],num[maxn],cnt,tot,ans; int n; void prime() { p[1]=1; for(int i=2;i<=1000000;i++) if(!p[i]){ b[++tot]=i;//素数 c[i]=tot; for(int j=i+i;j<=1000000;j+=i) p[j]=1; } } int Laxt[maxn],Next[maxm],To[maxm]; int linker[maxm],vis[maxn]; void add(int u,int v) { Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; } bool find(int u,int fa) { for(int i=Laxt[u];i;i=Next[i]){ int v=To[i]; if(vis[v]==fa) continue; vis[v]=fa; if(!linker[v]||find(linker[v],fa)){ linker[v]=u; return true; } } return false; } int main() { prime(); int i,j,x; scanf("%d",&n); for(i=1;i<=n;i++){ scanf("%d",&x); for(j=1;j<=tot;j++){ if(x%b[j]==0){ add(i,j); } } if(!find(i,i)) break; } printf("%d\n",i-1); return 0; }
It is your time to fight!