题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3988
题意:
给你n个数,如果{i, j}满足i!=j && a[i]+a[j]是一个质数,那么称{i, j}是个Pset
之后再给你一个k,然你找出最多k个这样的Pset二元组,使得所有二元组中出现的元素尽可能多
例如样例:
5 3
3 4 12 3 6
满足条件的二元组只有(1, 2)和(2, 4),所以这两个都选上就好了,答案为3
思路:
暴力所有二元组{i, j}
如果{i, j}是个Pset,并且a[i]!=1 || a[j]!=1,那么i到j连一条无向边
这个时候得出的图很显然是二分图
为什么呢?因为质数一定是个奇数(除了2,不过a[i]!=1 || a[j]!=1所以不会出现2这种情况),而奇数=奇数+偶数
这样的话每条边的两端一定是个奇数和一个偶数,把所有奇数的点放在左边,偶数放在右边,得证
……
到这里问题就好办了,贪心就好了
求出二分图的最大匹配,最大匹配中的每个Pset都会对答案贡献2,除此之外剩下所有没有用的1,两两配对对答案贡献也是2(不过注意一个细节:例如样例1 1 4 13,如果1和4匹配上了就错了!所以二分匹配时一定要让1最后匹配),贡献为2的Pset处理完了,剩下的贡献一定只能为1了,加上就是答案
#include<stdio.h>
#include<string.h>
#include<vector>
#include<algorithm>
using namespace std;
#define LL long long
vector<int> G[3005];
int n, a[3005], vis[3005], val[3005], link[3005], flag[2000005] = {1,1};
int Sech(int x)
{
int i, v;
for(i=0;i<G[x].size();i++)
{
v = G[x][i];
if(vis[v]==0)
{
vis[v] = 1;
if(link[v]==0 || Sech(link[v]))
{
link[v] = x;
link[x] = v;
return 1;
}
}
}
return 0;
}
int main(void)
{
LL i, j;
int T, k, sum, ans, s1;
for(i=2;i<=2000000;i++)
{
if(flag[i])
continue;
for(j=i*i;j<=2000000;j+=i)
flag[j] = 1;
}
scanf("%d", &T);
while(T--)
{
scanf("%d%d", &n, &k);
for(i=1;i<=n;i++)
{
scanf("%d", &a[i]);
G[i].clear();
}
s1 = 0;
memset(val, 0, sizeof(val));
for(i=1;i<=n;i++)
{
if(a[i]==1)
s1++;
for(j=i+1;j<=n;j++)
{
if(flag[a[i]+a[j]]==0)
{
val[i] = val[j] = 1;
if(a[i]%2 && a[j]!=1)
G[i].push_back(j);
else if(a[i]!=1)
G[j].push_back(i);
}
}
}
ans = sum = 0;
memset(link, 0, sizeof(link));
for(i=1;i<=n;i++)
{
if(a[i]!=1)
{
memset(vis, 0, sizeof(vis));
sum += Sech(i);
}
}
for(i=1;i<=n;i++)
{
if(a[i]==1)
{
memset(vis, 0, sizeof(vis));
sum += Sech(i);
}
}
for(i=1;i<=n;i++)
{
if(a[link[i]]==1)
s1--;
}
if(k<=sum)
printf("%d\n", k*2);
else
{
ans = sum*2;
k -= sum;
if(k*2<=s1)
printf("%d\n", ans+k*2);
else
{
ans += s1/2*2;
k -= s1/2;
for(i=1;i<=n;i++)
{
if(k==0)
break;
if(a[i]==1)
{
if(link[i]==0 && val[i] && s1%2)
{
s1 = 0;
ans++, k--;
}
}
else if(link[i]==0)
{
ans += val[i];
k -= val[i];
}
}
printf("%d\n", ans);
}
}
}
return 0;
}