二分图匹配其实十分简单,原理只有一个,能换则换,腾出这个妹子的位置,不要考虑其他人是不是很不满意从他喜欢中最喜欢的那一个变成了他喜欢中的最不喜欢的那一个,知道了这个原理,n遍DFS就可以过了:
#include<stdio.h>
#include<string.h>
const int Inf=1e9+10,maxn=5010,maxm=5010,maxe=10010;
int gi(){
int sum=0,f=1;char ch=getchar();
while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9' && ch>='0'){sum=sum*10+ch-'0';ch=getchar();}
return sum*f;
}
struct node{
int to,next;
}e[maxe];
int cnt,front[maxn],use[maxn];
int used[maxm],b[maxm],n,m;
void Add(int u,int v){
e[++cnt].to=v;
e[cnt].next=front[u];
front[u]=cnt;
}
bool dfs(int u){//寻找增广路
for(int i=front[u];i;i=e[i].next)
if(!used[e[i].to]){
used[e[i].to]=1;
if(b[e[i].to]==0 || dfs(b[e[i].to])){
use[u]=e[i].to;
b[e[i].to]=u;
return true;
}
}
return false;
}
int ED(){
int ans=0;
for(int i=1;i<=n;i++)
if(!use[i]){
memset(used,0,sizeof(used));
if(dfs(i))ans++;
}
return ans;
}
int main(){
int i,j,k,e;
scanf("%d%d%d",&n,&m,&e);
for(i=1;i<=e;i++){
int u=gi(),v=gi();
if(u<=n && v<=m)Add(u,v);
}
printf("%d\n",ED());
return 0;
}
以上为邻接表版本,如果有需要的,以下是邻接矩阵版本
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
int n,m;
int g[1010][1010];
int flag[1010],b[1010];
bool dfs(int u);
int ED();
void init();
int main(){
init();
return 0;
}
void init(){
int i,j,k,e;
scanf("%d%d%d",&n,&m,&e);
for(i=1;i<=e;i++){
int u,v;
scanf("%d%d",&u,&v);
if(u>n || v>m)continue;
g[u][v]=1;
}
printf("%d\n",ED());
}
int ED(){
int ans=0;
for(int i=1;i<=n;i++){
memset(flag,0,sizeof(flag));
if(dfs(i))ans++;
}
return ans;
}
bool dfs(int u){
for(int v=1;v<=m;v++)
if(g[u][v] && !flag[v]){
flag[v]=1;
if(!b[v] || dfs(b[v])){
b[v]=u;
return true;
}
}
return false;
}
时间: 2024-09-30 06:09:28