#素数伴侣#呆喵挠琴->匈牙利算法终极举例注释版本
素数伴侣
https://www.nowcoder.com/practice/b9eae162e02f4f928eac37d7699b352e
#include <iostream>
#include <vector>
using namespace std;
bool isprime(int i)
{
for (int j=2; j*j<=i; j++)
{
if(i%j==0)
return false;
}
return true;
}
// vector<int> match(even.size(),-1);
// vector<bool> visit(even.size(), false);
// n是需要匹配的奇数
bool find(const int &n,vector<vector<bool>> &map,vector<int> &match,vector<bool> &visit)
{
for (int i=0; i<match.size(); i++)
{
if(!visit[i]&&map[i][n])//没有访问过且能形成素数伴侣 n-odd i-even
{
visit[i]=true;
if(match[i]==-1||find(match[i], map, match,visit))// 没有匹配过||或者是匹配过的奇数 重新进行匹配
{
match[i]=n;
return true;
}
}
}
return false;
}
/*
1.代码流程- 先按照输入分为 odd 和 even 素数情侣只能在奇数+偶数里面 但并不是所有的奇数+偶数都是素数
2.遍历每个奇数和每个偶数的组合形成 map子图
3.find函数是最为关键的函数 输入:所求的奇数/ map子图/ match 记录该偶数所匹配的奇数(唯一)
/vist判断该偶数是否有访问过(每个新的奇数都刷新vist) vist数组的作用 防止被重复访问
举例说明 A可以匹配 a 和b B只可以匹配a
运行过程: if(!visit[i]&&map[i][n]) -> a没有被访问过且 A和a可以匹配
visit[i]=true; -> 记录a被访问过了
if(match[i]==-1||find(match[i], map, match,visit)) ->此时a没有被匹配过 前者成立
match[i]=n;//记录 a所匹配的为A
此时A-a形成关系
进行下个循环 寻找B的匹配关系 此时vist数组被刷新了
运行过程: if(!visit[i]&&map[i][n]) -> a没有被访问过且B和a可以匹配
visit[i]=true; -> 记录a被访问过了 (保证递归的时候不会被重复访问)第一次访问
if(match[i]==-1||find(match[i], map, match,visit)) -> a被匹配过了-前者不通过 //此时还在找B的
// a被占用了已经 B想抢a 那要问A是否有空余的? 如果有 A更换匹配关系 如果没有 A与a绑死 B找下一个匹配关系
-> ||递归进入 匹配a的是A 进入A的递归函数 a已经被访问过了(第二次) 进入b b与A可以匹配
更新匹配关系 A与b匹配 返回true 此时递归结束
判断为真
B与a 更新匹配关系
match[i]=n;//记录 a所匹配的为B
*/
int main()
{
int n=0;
while (cin>>n)
{
int k=0;
vector<int> even;
vector<int> odd;
int count=0;
while (n--)
{
cin>>k;
if(k%2==0)
{
odd.push_back(k);
}
else
{
even.push_back(k);
}
}
if(odd.empty()||even.empty())
{//奇数或偶数为空则不会有素数伴侣
cout<<count<<endl;
continue;
}
vector<vector<bool>> map(even.size(),vector<bool>(odd.size(),false));
for(int i=0;i<even.size();i++)//建立关系图,找出所有可能的连接
{
for(int j=0;j<odd.size();j++){
if(isprime(even[i]+odd[j])){
map[i][j]=true;
}
}
}
vector<int> match(even.size(),-1);
for (int i = 0; i < odd.size(); i++)//以奇数为核心遍历
{
vector<bool> visit(even.size(), false);//建立在当前奇数下对偶数的访问情况
if (find(i, map, match, visit))
{
count++;
}
}
cout << count << endl;
}
return 0;
}
// 64 位输出请用 printf("%lld")
查看17道真题和解析