最大二分图匹配是典型的图论问题,一般有两种做法,一种是运用最大流的思想,不过这种方法效率太低,为O(VE^2),没有利用好二分图的特殊性质。另一种做法是匈牙利
算法,这种方法也是利用了增益路径的思想,但这种方法充分利用了二分图的性质,所以效率也是比较高的,为O(VE),而且还能进一步降低,不过我没有做那种优化,下面就是我
的代码:
#include<iostream>
#include<queue>
#include<vector>
#include<stdio.h>
using namespace std;
class B_Graph
{
private:
struct vertex
{
bool flag ; //是否被标记
int ver ; //标记的顶点
vector<int>adj;
vertex(bool f=0,int v=0):flag(f),ver(v){}
};
struct Matching
{
int ww;
int uu;
Matching(int w=0,int u=0):ww(w),uu(u){}
void print(){
cout<<"("<<ww<<","<<uu<<") ";
}
};
int N1,N2; //点数,N1为V,N2为U
vector<vertex>V;
vector<Matching>M;
public:
B_Graph(int n1,int n2):N1(n1),N2(n2)
{
vertex tmp;
Matching tmp1;
for(int i=0;i<=N1+N2;i++)
V.push_back(tmp);
for(int i=0;i<=N1;i++)
M.push_back(tmp1);
}
void merge(int i,int j)
{
V[i].adj.push_back(j);
}
void Max_B_Maching()
{
queue<int>Q;
int i1=0;
while(i1++<N1)
Q.push(i1);
while(!Q.empty())
{
int w=Q.front();Q.pop();
if(w<=N1) //即w属于V
{
for(unsigned int i=0;i<V[w].adj.size();i++)
{
int u=V[w].adj[i];
if(V[u].flag==0)
{
Matching tmp(w,u);
M[w]=tmp;
V[u].flag=1;
V[w].flag=1;
int v=w;
while(V[v].ver)
{
u=V[v].ver;
v=V[u].ver;
Matching tmp2(v,u);
M[v]=tmp2;
V[v].flag=1;
}
for(int i=1;i<=N1+N2;i++)
V[i].ver=0;
while(!Q.empty())
Q.pop();
for(int i=1;i<=N1;i++)
if(V[i].flag==0)
Q.push(i);
break;
}
else
{
if((M[w].ww!=w||M[w].uu!=u)&&V[u].ver==0)
{
V[u].ver=w;
Q.push(u);
}
}
}
}
else
{
int i=1;
for(;i<=N1;i++)
if(M[i].uu==w)
{
V[i].ver=w;
break;
}
Q.push(i);
}
}
}
void print_M_maching()
{
for(int i=1;i<=N1;i++)
if(M[i].ww!=0)
M[i].print();
}
int max_maching()
{
int Max=0;
for(int i=1;i<=N1;i++)
if(M[i].ww!=0)
Max++;
return Max;
}
};
int main()
{
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
int v,u,edge;
while(cin>>v>>u>>edge)
{
B_Graph G(u,v);
int a,b;
while(edge--)
{
cin>>a>>b;
G.merge(a,b);
}
G.Max_B_Maching();
G.print_M_maching();
cout<<endl<<"The Max_maching number is:"<<G.max_maching()<<endl;
}
fclose(stdin);
fclose(stdout);
return 0;
}
下面是in.txt的测试数据:
5 5 10
1 6
1 7
2 6
3 6
3 8
4 8
4 9
4 10
5 9
5 10
4 4 8
1 6
2 6
2 7
3 6
3 7
4 5
4 7
4 8
最后是out.txt的结果:
(1,7) (2,6) (3,8) (4,9) (5,10)
The Max_maching number is:5
(1,6) (2,7) (4,5)
The Max_maching number is:3
结果正确!OK!