ZOJ 3988 Prime Set (二分图最大匹配+变形!!!)

xiaoxiao2025-10-06  27

Prime Set


Time Limit: 2 Seconds      Memory Limit: 131072 KB


Given an array of  integers , we say a set  is a prime set of the given array, if  and  is prime.

BaoBao has just found an array of  integers  in his pocket. He would like to select at most  prime set of that array to maximize the size of the union of the selected sets. That is to say, to maximize  by carefully selecting  and , where  and  is a prime set of the given array. Please help BaoBao calculate the maximum size of the union set.

Input

There are multiple test cases. The first line of the input is an integer , indicating the number of test cases. For each test case:

The first line contains two integers  and  (, ), their meanings are described above.

The second line contains  integers  (), indicating the given array.

It's guaranteed that the sum of  over all test cases will not exceed .

Output

For each test case output one line containing one integer, indicating the maximum size of the union of at most  prime set of the given array.

Sample Input

4 4 2 2 3 4 5 5 3 3 4 12 3 6 6 3 1 3 6 8 1 1 1 0 1

Sample Output

4 3 6 0

Hint

For the first sample test case, there are 3 prime sets: {1, 2}, {1, 4} and {2, 3}. As , we can select {1, 4} and {2, 3} to get the largest union set {1, 2, 3, 4} with a size of 4.

For the second sample test case, there are only 2 prime sets: {1, 2} and {2, 4}. As , we can select both of them to get the largest union set {1, 2, 4} with a size of 3.

For the third sample test case, there are 7 prime sets: {1, 3}, {1, 5}, {1, 6}, {2, 4}, {3, 5}, {3, 6} and {5, 6}. As , we can select {1, 3}, {2, 4} and {5, 6} to get the largest union set {1, 2, 3, 4, 5, 6} with a size of 6.

题意:给你n个数你需要选出k对数,使得覆盖尽可能多的数。

思路:还是比较容易想到二分图最大匹配的。

对于可以构成素数的数下标进行建边,跑匈牙利算法。

注意:已经选过的点不能再选。所以在匹配时需要加条件。当前点未匹配则可以进行匹配。(就是这个地方,题解都没说,害的我一度以为自己的匈牙利算法模板是假的,题解大神们能不能长点心,这样对萌新很不友好的。)

所以这个题并不是匈牙利算法的模板题,而是要进行修改。

获得最大匹配数sum以后,若k<=sum,则答案明显就是2*k,否则就是

2*sum+min(k-sum,图中建了边的而且未匹配的点的个数)

所以建了边的点我们要标记。

代码:

#include<bits/stdc++.h> #define ll long long #define inf 0x3f3f3f3f3f3f3f3fLL #define maxn 3010 #define maxm 2000010 using namespace std; int n,m,k,p,ans,sum; int g[maxn],us[maxn],a[maxn]; bool ok[maxm]; vector<int>vc[maxn]; bool dfs(int u) { us[u]=true; for(int v=0;v<vc[u].size();v++) { if(!us[vc[u][v]]){ us[vc[u][v]]=true; if(g[vc[u][v]]==-1||dfs(g[vc[u][v]])){ g[vc[u][v]]=u; g[u]=vc[u][v]; return true; } } } return false; } int pipei() { int ans=0; for(int u=1;u<=n;u++) { if(g[u]==-1) { memset(us,0,sizeof(us)); if(dfs(u)) ans++; } } return ans; } int main() { ok[1]=1; for(int i=2;i<maxm;++i){ for(ll j=(ll)i*(ll)i;j<maxm;j+=(ll)i){ ok[j]=1; } } int T,cas=1,x,y,c; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) { vc[i].clear(); g[i]=0; scanf("%d",&a[i]); } for(int i=1;i<=n;i++) { for(int j=i+1;j<=n;j++) if(!ok[a[i]+a[j]]) { vc[i].push_back(j); vc[j].push_back(i); g[i]=g[j]=-1; } } int sum=pipei(); if(sum>=k) printf("%d\n",2*k); else { int cnt=0; for(int i=1;i<=n;i++) if(g[i]==-1) cnt++; int ans=sum*2+min(k-sum,cnt); printf("%d\n",ans); } } return 0; } /* 4 4 2 2 3 4 5 5 3 3 4 12 3 6 6 3 1 3 6 8 1 1 1 0 1 */

 

转载请注明原文地址: https://www.6miu.com/read-5037478.html

最新回复(0)