1. 程式人生 > >zoj3988 Prime Set

zoj3988 Prime Set

lib clas pri span inf 二分圖 fin pac ace

思路不難想到二分圖求個最大匹配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; }

zoj3988 Prime Set