匈牙利算法解决HJ28“素数伴侣”问题
对匈牙利算法的理解:
主要用来解决二分图最多匹配数问题(指派问题)。
1、根据“匈牙利算法”,首先将输入的数分成奇数和偶数两部分:odd, even
2、根据odd中的数+even中的数是否可以组成素数,来构建图的邻接矩阵G
3、遍历每一个even中的元素,来匹配odd中的数,可以匹配则+1。
4、核心概念:在将even[i]匹配到一个odd[x]时,如果此时odd[x]已经匹配到了其他的even,则需要递归的去给odd[x]目前对应的even去匹配新的odd,如果匹配不到,则给even[i]匹配下一个odd。
匈牙利算法的学习,可以参考这位老兄:https://zhuanlan.zhihu.com/p/96229700
#include <bits/stdc++.h>
using namespace std;
class SolutionHJ28 {
private:
bool dfs(int i, vector<int> &odd, vector<vector<bool>> &g, vector<bool> &vis, vector<int> &p) {
for (int j = 0; j < odd.size(); j++) {
if (g[i][j] && !vis[j]) {
vis[j] = true;
if (p[j] == -1 || dfs(p[j], odd, g, vis, p)) {
p[j] = i;
return true;
}
}
}
return false;
}
public:
int getMaxNum(vector<int>& vec) {
vector<bool> ss(60001, true);
ss[0] = ss[1] = false;
for (int i = 2; i <= 60000; i++) {
if (ss[i] == true) {
int t = 2;
for (int j = i * t; j <= 60000; j = (++t) * i) {
ss[j] = false;
}
}
}
vector<int> even, odd;
for (int i = 0; i < vec.size(); i++) {
if (vec[i] % 2 == 0) {
even.push_back(vec[i]);
} else {
odd.push_back(vec[i]);
}
}
// 构造邻接矩阵
vector<vector<bool>> g(even.size(), vector<bool>(odd.size(), 0));
for (int i = 0; i < even.size(); i++) {
for (int j = 0; j < odd.size(); j++) {
if (ss[even[i] + odd[j]] == true) {
g[i][j] = 1;
}
}
}
vector<int> p(odd.size(), -1); // 记录右侧对应的左侧元素index
vector<bool> vis(odd.size(), false);
int cnt = 0;
for (int i = 0; i < even.size(); i++) {
vis.assign(odd.size(), false);
if (dfs(i, odd, g, vis, p)) {
cnt++;
}
}
return cnt;
}
};
void testHJ28() {
SolutionHJ28 s;
vector<int> vec{2, 5, 6, 13};
cout << s.getMaxNum(vec) << endl;
}

浙公网安备 33010602011771号