D唐纳德和他的数学老师(华师网络赛)(二分匹配,最大流)

Time limit per test: 1.0 seconds

Memory limit: 256 megabytes

唐纳德是一个数学天才。有一天,他的数学老师决定为难一下他。他跟唐纳德说:「现在我们来玩一个游戏。这个游戏总共 n轮,每一轮我都会给你一个数(第 i 轮给出的数是 ai)。你每次要回答一个数,是我给出的这个数的质因数,并且你说出的数不能重复。」

因为数学老师是刻意为难,所以这个游戏很有可能不可能进行到最后。但是聪明的数学老师早就已经知道这个游戏最多能进行几轮了。现在他把问题抛给了你,想看看你知不知道。

注意,1 不是质数。

Input

输入具有如下形式:

na1 a2  an

第一行一个整数 n (1n3 000)。

第二行 n 个整数用空格隔开,a1,a2,,an (2ai106)。

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
",i-1);
    return 0;
}
原文地址:https://www.cnblogs.com/hua-dong/p/8011175.html