简介
luogu模版题传送门传送门
二分图匹配的问题是可以被网络流解决的,接下来我们来学习一下二分图匹配。
二分图匹配所使用的算法是匈牙利算法,由于匈牙利人的脑回路可能和正常人不大一样,这个算法比较的暴力,并且算法运行过程也比较有趣。
首先,我来介绍一下匈牙利算法。
匈牙利算法可以用一句话简单的概括,就是绿与被绿协调与被协调。
算法介绍
然后我来正经的说一下匈牙利算法真正的算法过程。
匈牙利算法的主要过程是,先从二分图的一侧的最小编号开始,然后向另外一侧的点从编号最小的点开始匹配。
后面的点重复以上操作,如果遇到冲突,就让这个后来的点先匹配上这个点,
与前面匹配到这个点的点被协调,重新向后寻找点进行匹配,如果无法匹配则停止匹配。
如果在向前协调时矛盾则按照上面的方式进行协调。
如果上面的协商失败,那么最大号的点继续向下匹配。
接下来是算法的演示,我相信看明白演示以后,整个算法原理和方法就很好理解了。
算法过程
我们先建出下面这个图
那么我们就开始匈牙利算法了, 红色的连边为匹配上的边
显然的是第一次是A和E连边,但是接下来的时候B要连边的时候需要进行协调了,所以说我们需要让A被协调,把E让给B,A就只好和F匹配了。
上一轮匹配完毕后图就变成呢个了下面这个样子,但是在进行下一步的时候就需要还需要一轮协商了。我们来看与C连边的最小编号的是F点了,那么我们强制C和F匹配,那么A就需要被协调了,那么A就只好和G匹配了,这轮的协商完成了。
那么进过上面的这个协商过后,我们的图就变成了下面这个样子,接下里我们就要 进行最复杂的协调和被协调的步骤了,和D能进行匹配的最小编号就是E了,而E和B匹配着,那么B就要被协商了。
那么我们来看下面这张图,是上面的话进行协商的过程图片,蓝色的是B在协商后只能连的边,那么连接的G又被A连接过,所以说A只能被协调,而A没有更大的编号连边来供他匹配了,所以说这一轮的协商失败,维持原来的情况。
那么下面没有可以待匹配的点了,所以匈牙利算法结束了,下面的图是匹配成功的图。
时间复杂度
通过上面的演示,我们可以发现最坏的情况下就是没连一条边就需要协调到底,那么时间复杂度就是 O ( n ³ ) O(n³) O(n³)了,当时最好的就是一连就匹配,就是 O ( n ) O(n) O(n)了。通常情况下我们就把他当作 O ( n ³ ) O(n³) O(n³)了。
代码
那么下面放个我的代码。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int n,m,e;
bool f[1001][1001],vis[1001];
int py[1001],px[1001];
bool dfs(int x)
{
for(int i=1;i<=m;i++)
if(f[x][i])
if(!vis[i])
{
vis[i]=1;
if(py[i]==-1||dfs(py[i]))
{
px[x]=i;
py[i]=x;
return 1;
}
}
return 0;
}
void Hungary()
{
int ans=0;
memset(px,-1,sizeof(px));
memset(py,-1,sizeof(py));
for(int i=1;i<=n;i++)
memset(vis,0,sizeof(vis)),ans+=dfs(i);
cout<<ans<<endl;
return;
}
int main()
{
scanf("%d%d%d",&n,&m,&e);
for(int i=1;i<=e;i++)
{
int x,y;
scanf("%d%d",&x,&y);
if(x>=1&&x<=n&&y>=1&&y<=m)
f[x][y]=1;
}
Hungary();
return 0;
}