给定一个二分图,其中左半部包含 n1 个点(编号 1∼n1),右半部包含 n2 个点(编号 1∼n2),二分图共包含 m条边。
数据保证任意一条边的两个端点都不可能在同一部分中。
请你求出二分图的最大匹配数。
二分图的匹配:给定一个二分图 G,在 G 的一个子图 M 中,M 的边集 {E} 中的任意两条边都不依附于同一个顶点,则称 M是一个匹配。
二分图的最大匹配:所有匹配中包含边数最多的一组匹配被称为二分图的最大匹配,其边数即为最大匹配数。
第一行包含三个整数 n1、 n2 和 m。
接下来 m
行,每行包含两个整数 u 和 v,表示左半部点集中的点 u 和右半部点集中的点 v 之间存在一条边。
输出一个整数,表示二分图的最大匹配数。
1≤n1,n2≤500,
1≤u≤n1,
1≤v≤n2,
1≤m≤105
用左边的点去匹配右边,如果右边的节点右匹配点。则尝试将右边节点匹配的节点重新匹配。如果成功那么该节点就匹配成功。
#include
#include
#include
using namespace std;
const int N = 510, M = 200010;
int e[M],ne[M],h[N],idx;
int n , m,n1,n2;
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 u)
{
for(int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
if(!st[j]) // 还没有匹配过
{
st[j] = true;
if(match[j] == 0 || find(match[j])) // 没有对应匹配的左节点 或者可以j节点的匹配节点可以重新匹配成功
{
match[j] = u; return true;
}
}
}
return false ;
}
int main()
{
cin>>n1>>n2>>m;
memset(h,-1,sizeof h);
while(m--)
{
int u,v;
cin>>u>>v;
add(u,v);
}
int res = 0;
for(int i = 1 ; i <= n1 ; ++ i)
{
memset(st,false,sizeof st); // 表示还没开始匹配任意一个节点 防止重复匹配。
if(find(i)) res ++ ;
}
cout<<res;
return 0;
}
止重复匹配。
if(find(i)) res ++ ;
}
cout<
}