算法步骤:
1.把所有点设为非匹配点,S=空集,所有边都是非匹配边。
2.寻找增广路,把路径上所有边状态取反,得到更大匹配Si。
3,重复2步,直到不存在增广路。
增广路即:从非匹配点开始,到非匹配点结束,中间经过的边满足:非匹配边和匹配边交替。
找增广路过程:
枚举左部点x,枚举其连接的右部点y,若y为匹配,由于x为匹配,则构成了长度为1的增广路。
若y匹配,则枚举y连接的所有左部点,做同样的操作,直到找到一个非匹配点。若找不到,则从x出发无法构成增广路。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M = 1e5+7;
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,val;}ee[M*2];
void add(int x,int y){ee[++cnt].nxt=head[x],ee[cnt].to=y,head[x]=cnt;}
int match[1010];
int vs[1010];
bool dfs(int x)
{
for(int i=head[x];i;i=ee[i].nxt)
{
int y=ee[i].to;
if(!vs[y])
{
vs[y]=1;
if(!match[y]||dfs(match[y]))
{
match[y]=x;
return true;
}
}
}
return false;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n,m,q;
cin>>n>>m>>q;
for(int i=1;i<=q;i++)
{
int u,v;
cin>>u>>v;
v+=n;
add(u,v),add(v,u);
}
int ans=0;
for(int i=1;i<=n;i++)
{
memset(vs,0,sizeof(vs));
if(dfs(i))ans++;
}
cout<<ans<<endl;
return 0;
}
顺便写一下输出一组最大匹配边:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M = 1e5+7;
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,val,op;}ee[M*2];
void add(int x,int y){ee[++cnt].nxt=head[x],ee[cnt].to=y,head[x]=cnt;}
int match[1010];
int vs[1010];
bool dfs(int x)
{
for(int i=head[x];i;i=ee[i].nxt)
{
int y=ee[i].to;
if(!vs[y])
{
vs[y]=1;
ee[i].op^=1;
bool f=dfs(match[y]);
if(!match[y]||f)
{
match[y]=x;
return true;
}
ee[i].op^=1;
}
}
return false;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n,m,q;
cin>>n>>m>>q;//左部图点数和右部图点数
for(int i=1;i<=q;i++)
{
int u,v;
cin>>u>>v;
v+=n;
add(u,v),add(v,u);
}
int ans=0;
for(int i=1;i<=n;i++)
{
memset(vs,0,sizeof(vs));
if(dfs(i))ans++;
}
cout<<ans<<endl;
for(int i=1;i<=n;i++)
{
for(int j=head[i];j;j=ee[j].nxt)
{
if(ee[j].op==1)
cout<<i<<" "<<ee[j].to<<endl;
}
}
return 0;
}