匈牙利算法解决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;
}

  

posted @ 2022-02-15 11:36  太极者  阅读(596)  评论(0)    收藏  举报