这是一种用增广路求二分图最大匹配的算法。
讲解的很详细的博客:https://www.byvoid.com/blog/hungary/
至于基础知识,我就不多讲了。其实它就是一直在找出一条路径能把二分图的左半部分的其中一个未匹配节点和右半部分的其中一个未匹配节点加入到已经匹配的节点中去。这就是关键。那个博客讲的很详细了。看了之后都知道是具体情况。
下面我根据自己的理解实现了一下这个算法(DFS方式)。
#include<iostream>
using namespace std;
#define MAX_NUM 1024
int Left=4;
int Right=3;
int vm[MAX_NUM];//节点对应的匹配节点
int edge[MAX_NUM][MAX_NUM];//左右部分连接情况
int count;
bool isVisited[MAX_NUM];//每次找增广路的时候,都要对它进行重置
int index=0;
void init()
{
memset(edge,0,sizeof(edge));
edge[0][4]=1;
edge[0][6]=1;
edge[1][6]=1;
// edge[1][7]=1;
edge[2][4]=1;
edge[2][5]=1;
edge[3][5]=1;
edge[3][6]=1;
}
bool can(int m)
{
for(int i=Left;i<Left+Right;i++)
{
if(edge[m][i])
{
if(isVisited[i])
continue;
isVisited[i]=true;
if(vm[i]==-1)
{
cout<<m<<"->"<<i<<" ";
vm[m]=i;
vm[i]=m;
return true;
}
else
{
if(can(vm[i]))
{
vm[m]=i;
vm[i]=m;
cout<<m<<"->"<<i<<" ";
return true;
}
}
}
}
return false;
}
void main()
{
memset(vm,-1,MAX_NUM);
init();
for(int i=0;i<Left;i++)
{
cout<<"第"<<index++<<"次为: ";
memset(isVisited,0,sizeof(isVisited));
isVisited[i]=true;
if(can(i))
count++;
else
cout<<"NULL";
cout<<endl;
}
cout<<count<<endl;
}