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;
}

结束了,来点个赞!

更多推荐