zoj3988 Prime Set

思路不难想到二分图求个最大匹配P,若P>=K,则2*K即可,否则应为P*2+min(K-P,未匹配且有度数不为0的顶点个数s)。但坑点在于有1的情况,所以如果直接建二分图去跑最大匹配会因为1的影响而无法得到实际上的最大匹配,所以索性不建二分图而直接去跑最大匹配,此时应记录的是每个顶点的匹配顶点即可。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<string>
#include<set>
#include<algorithm>
#include<vector>
#include<queue>
#include<list>
#include<cmath>
#include<cstring>
#include<map>
#include<stack>
using namespace std;
#define INF 0x3f3f3f3f
#define maxn 2000005
#define ull unsigned long long
#define ll long long
#define hashmod 99999839
#define mod 9997
bool isprim[maxn],f[3005];
int pre[3005];
int prim[maxn],len,a[3005];
vector<int> vec[3005];
void init(){
    for(int i = 2;i < maxn;i++) isprim[i] = true;
    for(int i = 2;i < maxn;++i){
        if(isprim[i]) prim[len++] = i;
        for(int j = 0;j < len;++j){
            if(i * prim[j] > maxn) break;
            isprim[i * prim[j]] = false;
            if(i % prim[j] == 0) break;
        }
    }
}
bool dfs(int v){//尝试匹配v
    f[v] = true;
    for(int i = 0;i < vec[v].size();++i){
        int t = vec[v][i];
        if(!f[t]){
            f[t] = true;
            if(!pre[t] || dfs(pre[t])){
                pre[t] = v;
                pre[v] = t;
                f[t] = false;
                f[v] = false;
                return true;
            }
        }
    }
    return false;
}
int main(){
  //  freopen("a.in","r",stdin);
 //   freopen("b.out","w",stdout);
    init();
    int T;
    cin >> T;
    int n,k;
    while(T--){
        scanf("%d%d",&n,&k);
        for(int i = 1;i <= n;++i){
            scanf("%d",&a[i]);
        }
        sort(a + 1,a + n + 1);
        for(int i = 1;i <= n;++i){
            for(int j = i + 1;j <= n;++j){
                if(isprim[a[i] + a[j]]) vec[i].push_back(j),vec[j].push_back(i);
            }
        }
        memset(f,false,sizeof(f));
        memset(pre,0,sizeof(pre));
        int ans = 0;
        for(int i = 1;i <= n;++i){
            if(!pre[i] && !f[i] && dfs(i)){
                ans++;
            }
        }
        if(ans >= k) ans = k * 2;
        else{
            k -= ans;
            ans = ans * 2;
            for(int i = 1;i <= n && k;++i){
                if(!pre[i]){
                    int sz = vec[i].size();
                    if(sz) k--,ans++;
                }
            }
        }
        for(int i = 1;i <= n;++i) vec[i].clear();
        printf("%d\n",ans);
    }
    return 0;
}

 

posted @ 2018-08-21 22:45  zhuiyicc  阅读(158)  评论(0编辑  收藏  举报