2017 CCPC秦皇島 H Prime Set(二分圖匹配)
阿新 • • 發佈:2018-12-16
是一個二分圖匹配
而我和舟神bbbbbbbbbbbbbbbbb了大概一個小時,不想寫二分圖,甚至想建網路流模型
我也是服了,可能這就是不會算時間複雜度的菜雞吧
題目思路:
1.打素數表
2.將奇數和偶數分開到兩邊,因為只有奇數加偶數才可以是素數。
3.1特殊處理,如果有兩個1,1之間也可以匹配,但優先考慮1和偶數的匹配,此處要注意細節,我用了兩個set來減少討論
#include<iostream> #include<set> #include<string.h> #include<algorithm> #include<stdio.h> #define N 3005 #define MAXN 2000005 using namespace std; int eve[N],odd[N]; bool isprime[MAXN]; int prime[150005],tot=0; void init(){ memset(isprime,true,sizeof(isprime)); isprime[1]=false; for(int i=2;i<=MAXN-1;i++){ if(isprime[i]){ prime[++tot]=i; } for(int j=1;j<=tot;j++){ if(i*prime[j]>MAXN-1) break; isprime[i*prime[j]]=0; if(i%prime[j]==0) break; } } //for (int i=1;i<=20;i++) cout<<i<<" "<<isprime[i]<<endl; } int head[N]; struct edge{ int v,next; }e[N*N]; void add(int u, int v){ e[++tot]=(edge){v,head[u]}; head[u]=tot; } bool vis[N]; int link[N]; int dfs(int s){ //vis[s]=1; ????? for(int i=head[s];i!=-1;i=e[i].next){ int t=e[i].v; if(!vis[t]){ vis[t]=1; if(link[t]==-1||dfs(link[t])){ link[t]=s; link[s]=t; return 1; } } } return 0; } int max_matching(int n) { int ans=0; for(int i=1;i<=n;i++){ if (link[i]==-1){ memset(vis,0,sizeof(vis)); ans+=dfs(i); } } return ans; } set<int>sodd,seven; int main(){ init(); int T; scanf("%d",&T); while (T--){ int n,k,tot1=0,tot2=0,x; scanf("%d%d",&n,&k); for (int i=1;i<=n;i++){ scanf("%d",&x); if (x%2) odd[++tot1]=x; else eve[++tot2]=x; } tot=0; memset(head,-1,sizeof(head)); sodd.clear(); seven.clear(); int last1=-1,sum1=0; for (int i=1;i<=tot1;i++){ if (odd[i]==1){ if (!sum1) last1=i,sum1++; else{ if (sum1==1) sodd.insert(last1); sodd.insert(i); sum1++; } } for (int j=1;j<=tot2;j++){ if (isprime[odd[i]+eve[j]]){ add(i,tot1+j); add(tot1+j,i); sodd.insert(i); seven.insert(j); } } } memset(link,-1,sizeof(link)); int mat=max_matching(tot1); //cout<<mat<<endl; //for (int i=1;i<=tot1+tot2;i++) printf("link%d\n",link[i]); if (mat>=k) printf("%d\n",k*2); else{ int tmp=0; for (int i=1;i<=tot1;i++){ if (odd[i]==1&&link[i]==-1) tmp++; } int ans=mat*2+tmp/2*2; if (ans>=2*k) printf("%d\n",k*2); else { ans=min(k*2,min(ans+k-mat-tmp/2,(int)sodd.size()+(int)seven.size())); printf("%d\n",ans); } } } return 0; } /* 10 5 5 1 1 1 1 1 6 5 1 1 1 1 2 2 6 3 1 1 1 1 1 3 6 5 5 1 1 1 1 1 */