C++ 图论之二分图最大匹配(匈牙利算法)

文章介绍了二分图的概念,强调了在二分图中不应存在自环。接着详细阐述了二分图匹配问题和匈牙利算法,包括其普通版和边表优化版的代码实现,用于寻找最大匹配数量,复杂度分别对应O(左边点数^2*右边点数)和O(左边点数*边数)。
摘要由CSDN通过智能技术生成

1.二分图是?

 就这样两边只有点中间只有边!竟然还***有自环。

2.二分图匹配!

左边一个点匹配右边一个点,且两点之间有连边,例如4号点只能匹配1号点。

可以用匈牙利算法来求最大匹配数量。

3.匈牙利算法(普通版)!

复杂度:O(左边点数^2*右边点数)

(1)代码介绍

原理:一个点去匹配,如果别的点占用了它的一条,那么让别的点取消匹配重新匹配自己匹配。如果没有可以匹配的,那个点可以洗洗睡了就不匹配了

bool match[505][505];
match[i][j]

代表左边第i个点和右边第j个点能不能匹配。 

long long n,m,e;

 左边有n个点,右边有m个点,有e条边。

bool vis[505];
vis[i]

 代表右边第i个点在这一轮中有没有被请求过匹配。

int result[505];
result[i]

 代表右边第i个点和左边第result[i]个点匹配。

(2)代码 (来了~)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
bool match[505][505];
ll n,m,e;
bool vis[505];
int result[505];
bool check(int i){//判定匹配。 
	for(int j=1;j<=m;j++){//让左边第i个点和右边第j个点尝试匹配。 
		if(match[i][j]&&!vis[j]){
			vis[j]=1;
			if(!result[j]||check(result[j])){
				result[j]=i;
				return 1;
			}
		}
	}
	return 0; 
} 
int main(){
	ll ans=0;
	cin>>n>>m>>e; 
	for(int i=1;i<=e;i++){
		ll v,u;
		cin>>v>>u;
		match[v][u]=1;
	}
	for(int i=1;i<=n;i++){
		memset(vis,0,sizeof(vis));
		if(check(i))ans++;//匹配成功! 
	}
	cout<<ans;
}

4.匈牙利算法(边表优化版)!

复杂度:O(左边点数*边数) 

(1)代码介绍 

match不要了!改用边表优化!边表如下。 

vector<long long> edge[505];

 (2)代码 (来了~)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
vector<ll> edge[505];
ll n,m,e;
bool vis[505];
int result[505]; 
void add_edge(ll s,ll e){
	edge[s].push_back(e);
} 
bool check(int i){//判定匹配。 
	for(int j=0;j<edge[i].size();j++){//让左边第i个点和右边与i相连的点尝试匹配。 
		ll k=edge[i][j];
		if(!vis[k]){
			vis[k]=1;
			if(!result[k]||check(result[k])){
				result[k]=i;
				return 1;
			}
		}
	}
	return 0; 
} 
int main(){
	ll ans=0;
	cin>>n>>m>>e; 
	for(int i=1;i<=e;i++){
		ll v,u;
		cin>>v>>u;
		add_edge(v,u);
	}
	for(int i=1;i<=n;i++){
		memset(vis,0,sizeof(vis));
		if(check(i))ans++;//匹配成功! 
	}
	cout<<ans;
}

结束了,来点个赞!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值