标签:二分 匹配 增广 int 华为 match 机试 100 gi
二分图:将节点分成两组,A和B,边都是横跨在两组之间的,组内是没有边的相连的
判断方法,染色法
匹配:边的集合,任意两个边都没有公共的节点
最大匹配:找出匹配的边集合最大
交错路
增广路径
需要证明的是没有增广路径的时候就是最大匹配了
知乎一篇写的很不错的文章
https://zhuanlan.zhihu.com/p/96229700
看了这个算法,用了男女生匹配的方式进行讲解,其实match函数就是在找增广路径
增广路径要以没有匹配的节点开始,
所以match(i)的时候,i前面的要么是已经match了
要么就是考虑过了,没法match
如果match(i) 返回是真,那么就是说还存在增广路径
否则就是考虑到i的最大匹配了
正常来说,我们应该考虑所有的情况,最后挑一个最大的匹配
这里复杂度变低的原因就是,算法只从前到后运行一次
增广路径不可能往前找,满足贪心的性质,所以复杂度就低了
看懂题解之后 耗时23min
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <algorithm>
using namespace std;
#define debug(x) cout<<#x<<": "<<(x)<<endl;
bool isp(int n){
int s = sqrt(n);
for(int i=2;i<=s;i++){
if(n%i==0){
return false;
}
}
return true;
}
int b[100];
int g[100];
bool l[100][100];
int v[100];
int bc;
int gc;
int p[100];
bool findg(int bi){
for(int gi=0;gi<gc;gi++){
if( l[bi][gi] && v[gi]==0){
v[gi] = 1;
if( p[gi]==-1 || findg( p[gi] ) ){
p[gi]=bi;
return true;
}
}
}
return false;
}
int main(){
int n;
while(scanf("%d",&n)!=EOF){
bc = 0;
gc = 0;
fill(p,p+100,-1);
for(int i=0;i<n;i++){
int a=0;
scanf("%d",&a);
if(a%2==0){
b[bc++] = a;
}else{
g[gc++] = a;
}
}
for(int i=0;i<bc;i++){
for(int j=0;j<gc;j++){
l[i][j] = isp(b[i]+g[j]);
}
}
int cnt=0;
for(int i=0;i<bc;i++){
fill(v,v+100,0);
if(findg(i)){
cnt++;
}
}
cout<<cnt<<endl;
}
return 0;
}
标签:二分,匹配,增广,int,华为,match,机试,100,gi 来源: https://blog.csdn.net/L1558198727/article/details/116209587
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。