匈牙利算法 \color{red}{\huge{匈牙利算法}} 匈牙利算法
匈牙利算法就是用来 二分图的最大匹配问题 \color{blue}{二分图的最大匹配问题} 二分图的最大匹配问题。该算法是匈牙利的一个数学家 E d m o n d s Edmonds Edmonds提出的,所以被后人称之为匈牙利算法。
最大匹配
.
.
?
\color{orange}{\huge{最大匹配..?}}
最大匹配..?
通俗一点来讲就是,对于一个二分图,①.所有的边都是两个点集合之间的。②.
一个边所连的两个点只能拥有当前这条边,不能够在连接其他的边了
\color{red}{一个边所连的两个点只能拥有当前这条边,不能够在连接其他的边了}
一个边所连的两个点只能拥有当前这条边,不能够在连接其他的边了。
满足这两个条件之后,求这样的边的条数。

把二分图左右两侧的点的集合分成 n 1 n_{1} n1和 n 2 n_{2} n2,执行算法流程:
for(每一个n1中的点)
{
for(遍历到当前n1中的点n1'所相连的n2中的点n2')
{
if(n2'现有的连接可以调整)
{
match[n2'] = n1';
res++; //匹配数
匹配成功返回
}
else
匹配失败
}
}
return res;

解释:一开始黑 1 1 1连接了红 1 1 1和红 2 2 2,那么黑 1 1 1就已经默认匹配好了对方的红 1 1 1,变为灰线。之后黑 2 2 2进行匹配,黑 2 2 2优先进行与红 1 1 1进行匹配,发现红 1 1 1已经有了匹配,于是溯源到黑 1 1 1,看黑 1 1 1可不可以调整一下匹配,使得黑 2 2 2与红 1 1 1进行匹配成功,答案是可以的。黑 1 1 1还可以与红 2 2 2进行匹配,于是调整一下,最后优化成为了黑 1 1 1匹配红 2 2 2,黑 2 2 2匹配红 1 1 1。优化完成。
h
[
N
]
,
e
[
M
]
,
n
e
[
M
]
,
i
d
x
h[N] , e[M] , ne[M] , idx
h[N],e[M],ne[M],idx:邻接表组件,老生常谈。
m
a
t
c
h
[
N
]
match[N]
match[N]:匹配函数,
m
a
t
c
h
[
j
]
=
a
match[j] = a
match[j]=a表示右侧
j
j
j对应的匹配是左侧的
a
a
a点。
s
t
[
N
]
st[N]
st[N]:标志右侧的点有没有对应左侧的匹配成功。
K e y : F i n d ( 寻找左侧点的一个右侧匹配, 返回是否成功 ) \color{red}{\huge{Key:}}Find(寻找左侧点的一个右侧匹配,\color{blue}{返回是否成功}) Key:Find(寻找左侧点的一个右侧匹配,返回是否成功)
bool Find(int x) //输入的参数是左侧的点
{
for(int i = h[x] ; i != -1 ; i = ne[i]) //遍历左侧点相邻的所有右侧点
{
int j = e[i];
if(!st[j]) //如果右侧点没有确定匹配
{
st[j] = true; //置成已经匹配成功的状态
if(match[j] == 0 || find(match[j])
//如果这个右侧点没有匹配或者对应之前左侧点的匹配能够调整
{
match[j] = x; //这个右侧点的匹配置为当前的左侧点
return ture;
}
}
}
return false;
}
#include
#include
#include
using namespace std;
const int N = 510 , M = 100010;
int n1,n2,m;
int h[N],e[M],ne[M],idx;
int match[N];
bool st[N];
void add(int a,int b)
{
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
bool find(int x)
{
for(int i = h[x] ; i != -1 ; i = ne[i])
{
int j = e[i];
if(!st[j])
{
st[j] = true;
if(match[j] == 0 || find(match[j]))
{
match[j] = x;
return true;
}
}
}
return false;
}
int main ()
{
cin >>n1 >> n2 >> m;
memset(h,-1,sizeof(h));
while(m--)
{
int a,b;
cin >> a >>b;
add(a,b);
}
int res = 0;
for(int i = 1 ; i <= n1 ; i++)
{
memset(st,false,sizeof(st));
if(find(i))
res++;
}
cout << res << endl;
return 0;
}