高维宇宙 【NOIP2016提高A组集训第3场10.31】

题目

这里写图片描述
样例输入:
这里写图片描述
5
2 9 11 12 37

样例输出:
这里写图片描述
2

数据范围:
这里写图片描述

剖解题目

给n个数,两两配对,要求是两个数的和必须是素数,配对后就不能再与其他的数配对。


解法

泪奔,学了网络流终于有用了/(ㄒoㄒ)/
~~尽管这道题很裸

由于ai很小,我们直接预处理出2000内的质数。
首先我们知道,如果两个数加起来要是个素数,他们首先得一奇数一偶数。
把奇数和偶数分为两类,这就是个二分图,做一遍最大匹配即可。
匈牙利或网络流都行。
最近我刚学网络流,所以就扔了网络流进去,尽管是一个最基础的。。。


代码

具体来讲,就是每一个奇数向能与它的和为质数的偶数连一条容量为1的边,然后源点向每一个奇数连一条容量为1的边,每一个偶数向汇点连一个容量为1的边。
手速upupupup。。。

#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#define fo(i,a,b) for(int i=a;i<=b;i++)

using namespace std;

const int maxn=42,maxm=2002;
int f[maxn][maxn],a[maxn],h[maxn];
int n,ans,id;
bool bz[maxm];

int aug(int x,int now)
{
    if (x==n+1) return now;
    h[x]=id;
    fo(i,0,n+1)
    if (h[i]<id&&f[x][i]){
        int k=aug(i,min(now,f[x][i]));
        if (k){
            f[x][i]-=k;
            f[i][x]+=k;
            return k;
        }
    }
    return 0;
}
int main()
{
    freopen("prime.in","r",stdin);
    freopen("prime.out","w",stdout);
    scanf("%d",&n);
    int maxx=0;
    fo(i,1,n) scanf("%d",&a[i]),maxx=max(maxx,a[i]);
    maxx*=2;
    fo(i,2,maxx)
    if (!bz[i]){
        fo(j,2,maxx/i) bz[i*j]=true;
    }
    fo(i,1,n)
    if (a[i]%2) {
        f[0][i]=1;
        fo(j,1,n)
        if (a[j]%2==0) f[i][j]=bz[a[i]+a[j]]^1;
    }
    else f[i][n+1]=1;
    int flow=0;
    do{
        ++id;
        flow=aug(0,10000);
        ans+=flow;
    }while (flow);
    printf("%d",ans);
}

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值