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;
}
结束了,来点个赞!