[CCPC] 2017秦皇岛H Prime Set | 二分图最大匹配 [据说是个金牌题]

简介: 题意:给出n个数,如果两数之和a i + a j a_i+a_ja i​ +a j​ (i ≠ j i \neq ji ​ =j)为素数,那么这两个数的下标组成的集合{ i , j } {\{i,j}\}{i,j}问最多挑选k个这样的集合,集合最大的大小是多少思路:将给出的n个数进行暴力两两求和,看两数之和是否为素数,将能够构成素数的两个数的下标连一条边开始将match数组标记为− 1 -1−1,如果能够构成素数,那么将这个数标记为0 00然后进行二分图最大匹配,如果说匹配的个数 ≥ k \ge k≥k 那么答案就是k ∗ 2 k*2k∗2

题目链接 or 题目链接


题目描述


Given an array of n integers a1,a2,…,an, we say a set {i,j} is a prime set of the given array, if i≠j and ai+aj is prime.

BaoBao has just found an array of n integers a1,a2,…,an in his pocket. He would like to select at most k 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 m and p1,p2,…,pm, where m≤k and pi is a prime set of the given array. Please help BaoBao calculate the maximum size of the union set.


输入


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

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

The second line contains n integers a1,a2,…,an(1≤ai≤106), indicating the given array.

It’s guaranteed that the sum of n over all test cases will not exceed 104.


输出


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


样例输入


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


样例输出


4
3
6
0


提示


For the first sample test case, there are 3 prime sets: {1, 2}, {1, 4} and {2, 3}. As k=2, 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 k=3, 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 k=3, 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个数,如果两数之和a i + a j a_i+a_ja

i

+a

j

(i ≠ j i \neq ji

=j)为素数,那么这两个数的下标组成的集合{ i , j } {\{i,j}\}{i,j}

问最多挑选k个这样的集合,集合最大的大小是多少


思路:


将给出的n个数进行暴力两两求和,看两数之和是否为素数,将能够构成素数的两个数的下标连一条边

开始将match数组标记为− 1 -1−1,如果能够构成素数,那么将这个数标记为0 00

然后进行二分图最大匹配,如果说匹配的个数 ≥ k \ge k≥k 那么答案就是k ∗ 2 k*2k∗2

如果说匹配的个数 < k \lt k


注意要将match进行双向标记,而且在进入d f s dfsdfs函数后进行标记


int n,k,a[30007];
vector<int> gra[30007];
bool ju[2000007];
int tot = 0;
int Pri[2000007];
void _Get_Prime() {
  ju[0] = 1;
  ju[1] = 1;
  for (register int i = 2; i <= 2000005; i++) {
    if (ju[i] == 0) {
      Pri[++tot] = i;
    }
    for (register int j = 1; j <= tot; j++) {
      if (i * Pri[j] >= 2000005) break;
      ju[i * Pri[j]] = 1;
      if (i % Pri[j] == 0) break;
    }
  }
}
void get() {
  memset(ju,1,sizeof ju);
  ju[0] = ju[1] = 0;
  for(int i=2; i<=2000000; i++) {
    for(int j=i+i; j<=2000000; j+=i) {
      ju[j] = 0;
    }
  }
}
bool vis[30007];
int fa[30007];
bool dfs(int x) {
  vis[x] = 1;
  int siz = gra[x].size();
  for(int i=0; i<siz; i++) {
    int to = gra[x][i];
    if(vis[to]) continue;
    vis[to] = 1;
    if(fa[to] == 0 || dfs(fa[to])) {
      fa[to] = x;
      fa[x] = to;
      return true;
    }
  }
  return false;
}
int main() {
  _Get_Prime();
//  get();
  int _ = read;
  while(_ --) {
    n = read,k = read;
    for(int i=1; i<=n; i++) {
      gra[i].clear();
      fa[i] = -1;
    }
    for(int i=1; i <= n; i++) a[i] = read;
    for(int i=1; i<=n; i++) {
      for(int j=i+1; j<=n; j++) {
        int sum = a[i] + a[j];
        if(!ju[sum]) {
          fa[i] = fa[j] = 0;
          gra[i].push_back(j);
          gra[j].push_back(i);
        }
      }
    }
    ll ans = 0;
    int cnt = 0;
    for(int i=1; i<=n; i++) {
      if(fa[i] != 0) continue;
      memset(vis,0,sizeof vis);
      if(dfs(i)) cnt ++;
    }
    if(cnt >= k) {
      ans = k * 2;
    } else {
      int rest = k - cnt;
      cnt *= 2;
      for(int i=1; i<=n; i++) {
        if(rest <= 0) break;
        if(fa[i] == 0) {
          rest --;
          cnt ++;
        }
      }
      ans = cnt;
    }
    printf("%d\n",ans);
//    debug(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
**/





目录
相关文章
POJ 2689 Prime Distance (埃氏筛 区间筛)
POJ 2689 Prime Distance (埃氏筛 区间筛)
126 0
|
机器学习/深度学习
LCM性质 + 组合数 - HDU 5407 CRB and Candies
CRB and Candies Problem's Link  Mean:  给定一个数n,求LCM(C(n,0),C(n,1),C(n,2)...C(n,n))的值,(n
1030 0
|
9月前
|
算法 测试技术 C#
【菲蜀定理 子序列】1250 检查「好数组」
【菲蜀定理 子序列】1250 检查「好数组」
|
人工智能
Educational Codeforces Round 21(A.暴力,B.前缀和,C.贪心)
A. Lucky Year time limit per test:1 second memory limit per test:256 megabytes input:standard input output:standard outp...
1296 0
|
机器学习/深度学习 Java
【每日一题Day64】LC1799N 次操作后的最大分数和 | 状态压缩dp 状态压缩+dfs+记忆化搜索
每个数字有两种状态,删除或者未删除,因此可以使用状态压缩记录未删除的数字情况state,便于使用位运算进行状态的遍历及转移;使用状态压缩dp找到将所以数字删除的最大分数
115 0
【每日一题Day64】LC1799N 次操作后的最大分数和 | 状态压缩dp 状态压缩+dfs+记忆化搜索
Wannafly模拟赛 A.矩阵(二分答案+hash)
矩阵 时间限制:1秒 空间限制:131072K 题目描述 给出一个n * m的矩阵。让你从中发现一个最大的正方形。使得这样子的正方形在矩阵中出现了至少两次。输出最大正方形的边长。 输入描述: 第一行两个整数n, m代表矩阵的长和宽; 接下来n行,每行m个字符(小写字母),表示矩阵; 输出描述: 输出一个整数表示满足条件的最大正方形的边长。
1282 0
|
机器学习/深度学习
[POJ] John‘s trip | 欧拉回路 | 边序列字典序最小 + 建图
Description Little Johnny has got a new car. He decided to drive around the town to visit his friends. Johnny wanted to visit all his friends, but there was many of them. In each street he had one friend. He started thinking how to make his trip as short as possible.
162 0
[POJ] John‘s trip | 欧拉回路 | 边序列字典序最小 + 建图
|
人工智能 Python
codeforces1151B Dima(异或的性质)
codeforces1151B题解(异或的性质)
1368 0
|
Java Go
组合数学 - 母函数的运用 --- 模板题
Holding Bin-Laden Captive! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 15064    Accepted ...
1143 0

热门文章

最新文章