华为机试---素数伴侣(二分图匹配+匈牙利算法)

在这里插入图片描述

每个数的取值范围是[2,30000] ,因为素数的话,除了2是偶数,其他是奇数——而现在不可能出现2了,所以我们只考虑奇数的素数 。
2个数的和是奇数,有什么情况呢? 只有奇数+偶数
所以,我们把这些数分成2堆——奇数和偶数,然后在他们中间,和是素数的,连上一条边,然后做匹配。
说明了得到的图一定是二分图。
因为对二分图的最大匹配,有一个简单很多的算法,匈牙利算法。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
#define mp make_pair
#define pb push_back
#define fi first
#define se second

bool prime[60005];
void init()
{
    memset(prime,true,sizeof(prime));
    prime[0] = false; prime[1] = false;
    for(int i = 2;i <= 60000;++i){
        if(prime[i]){
            if(i * i > 60000) break;
            for(int j = i * i;j <= 60000;j += i){
                prime[j] = false;
            }
        }
    }
}

int n;
vector<int>ve[105];
int a[105];
bool vis[105];
int cc[105];

bool dfs(int u)
{
    int len = ve[u].size();
    for(int i = 0;i < len;++i){
        int v = ve[u][i];
        if(!vis[v]){
            vis[v] = true;
            if(cc[v] == -1 || dfs(cc[v])){
                cc[u] = v;
                cc[v] = u;
                return true;
            }
        }
    }
    return false;
}

void solve()
{
    int ans = 0;
    memset(cc,-1,sizeof(cc));
    for(int i = 1;i <= n;++i){
        if(cc[i] == -1){
            memset(vis,false,sizeof(vis));
            vis[i] = true;
            ans += dfs(i);
        }
    }
    cout << ans << endl;
}


int main()
{
    while(~scanf("%d",&n)){
        init();
        for(int i = 1;i <= n;++i){
            ve[i].clear();
            scanf("%d",&a[i]);
        }
        for(int i = 1;i <= n;++i){
            for(int j = i + 1;j <= n;++j){
                if(prime[a[i] + a[j]]){
                    ve[i].pb(j);
                    ve[j].pb(i);
                }
            }
        }
        solve();
    }
    return 0;
}

匈牙利算法的伪代码和实际代码:

cx[i]表示与X部i点匹配的Y部顶点编号 
cy[i]表示与Y部i点匹配的X部顶点编号
//伪代码
bool dfs(int u)//寻找从u出发的增广路径
{
    for each v∈u的邻接点
        if(v未访问){
            标记v已访问;
            if(v未匹配||dfs(cy[v])){
                cx[u]=v;
                cy[v]=u; 
                return true;//有从u出发的增广路径
            }
        }
    return false;//无法找到从u出发的增广路径
}
//代码
bool dfs(int u){
    for(int v=1;v<=m;v++)
        if(t[u][v]&&!vis[v]){
            vis[v]=1;
            if(cy[v]==-1||dfs(cy[v])){
                cx[u]=v;cy[v]=u;
                return 1;
            }
        }
    return 0;
}
void maxmatch()//匈牙利算法主函数
{
    int ans=0;
    memset(cx,0xff,sizeof cx);
    memset(cy,0xff,sizeof cy);
    for(int i=0;i<=nx;i++) 
        if(cx[i]==-1)//如果i未匹配
        { 
            memset(visit,false,sizeof(visit)) ; 
            ans += dfs(i); 
        }
    return ans ;
} 
发布了269 篇原创文章 · 获赞 33 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/qq_36386435/article/details/100141667