[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
**/





目录
相关文章
|
5月前
|
算法
【每日一题Day363】LC275H 指数Ⅱ | 二分答案
【每日一题Day363】LC275H 指数Ⅱ | 二分答案
35 0
|
7月前
|
机器学习/深度学习 算法 数据安全/隐私保护
华为机试HJ28:素数伴侣
华为机试HJ28:素数伴侣
|
11月前
|
C++ Windows 容器
【PAT甲级 - C++题解】1063 Set Similarity
【PAT甲级 - C++题解】1063 Set Similarity
38 0
|
11月前
|
算法 C++
【PAT甲级 - C++题解】1029 Median
【PAT甲级 - C++题解】1029 Median
50 0
|
11月前
|
存储 C语言 C++
【PAT甲级 - C++题解】1012 The Best Rank
【PAT甲级 - C++题解】1012 The Best Rank
30 0
|
11月前
|
人工智能 BI 文件存储
【PAT甲级 - C++题解】1103 Integer Factorization
【PAT甲级 - C++题解】1103 Integer Factorization
60 0
|
11月前
|
机器学习/深度学习 C++
【PAT甲级 - C++题解】1060 Are They Equal
【PAT甲级 - C++题解】1060 Are They Equal
31 0
|
12月前
|
人工智能
51nod 1354 选数字 (01背包问题好题)
51nod 1354 选数字 (01背包问题好题)
37 0
|
人工智能 BI
upc-2021个人训练赛第27场 D: Values(思维+并查集)
upc-2021个人训练赛第27场 D: Values(思维+并查集)
64 0
|
人工智能 Java
HDU-敌兵布阵(线段树 || 树状数组)
HDU-敌兵布阵(线段树 || 树状数组)
68 0