2017CCPC秦皇岛 H题Prime Set&&ZOJ3988

题意:

 定义一种集合,只有两个数,两个数不同且加起来为素数。要从n个数里抽出数字组成该集合(数字也可以是1~n,这个好懵圈啊),要求你选择最多k个该种集合组成一个有最多元素的集合,求出元素的数量。

思路:

代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;

const int maxn=3000+10;
const int masn=2e6+10;

int n,m,ans,head[maxn],p[maxn],a[maxn];
bool vis[maxn],prime[masn];
vector<int> g[maxn];

bool slove(int x)
{
    vis[x]=true;
    int len=g[x].size();
    for(int i=0;i<len;i++)
    {
        int v=g[x][i];
        if(!vis[v])
        {
            vis[v]=true;
            if(a[v]==0||slove(a[v]))
            {
                a[v]=x;
                a[x]=v;
                return true;
            }
        }
    }
    return false;
}

int main()
{
    for(int i=2;i<masn;i++)
        if(!prime[i])
          for(int j=i+i;j<masn;j+=i)
            prime[j]=true;
    void add_(int,int);
    bool slove(int);
    int t;
    cin>>t;
    while(t--)
    {
        ans=1;
        memset(head,-1,sizeof(head));
        cin>>n>>m;
        for(int i=1;i<=n;i++)
        {
            cin>>p[i];
            g[i].clear();
        }
        memset(a,-1,sizeof(a));
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
                if(!prime[p[i]+p[j]])
                {
                    g[i].push_back(j);
                    g[j].push_back(i);
                    a[i]=a[j]=0;
                }
        int sumn=0,summ=0;
        for(int i=1;i<=n;i++)
            if(a[i]==0)
            {
                memset(vis,false,sizeof(vis));
                if(slove(i))
                    sumn++;
            }
        for(int i=1;i<=n;i++)
            if(a[i]==0)
               summ++;
        if(sumn>=m)
           cout<< 2*m <<endl;
        else
        {
            int w=m-sumn;
            cout<< sumn*2+min(w,summ) <<endl;
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/darklights/p/7774015.html