这题属于二分图算法的入门题目。
就是要求二分图的最大匹配。求解最大匹配的算法为匈牙利算法。其核心思想就是从左半点集逐个出发寻找增广路径,每找到
一条增广路径,匹配数就加一。可以证明当找不到增广路径是就得到了最大匹配。
详细解释请参阅:点击打开链接
其中,useif[]是在同一次寻找增广路径是有用。主要是由于递归。比如如果之前已用过右点集中的1,下一次就不能再用了。
开始时初始化num=0,表示初始匹配为0。即表明左点集中每一点都是未用,也即都可以作为寻找增广路径的起点。
AC代码:
#include<iostream>
using namespace std;
const int MAX=501;
int lNum,rNum,k;
int link[MAX]; //记录当前与y点相连的x点
bool map[MAX][MAX]; //存储二分图,x到y有路径,则map[x][y]=true;反之,为false
bool useif[MAX]; //记录y中节点是否使用了(也就是男生是否已经被选)
void getMap() //存图
{
memset(map,false,sizeof(map));
int x,y;
for(int i=1;i<=k;i++)
{
cin>>x>>y;
map[x][y]=true;
}
}
bool can(int t)
{
for(int i=1;i<=lNum;i++)
{
if(!useif[i] && map[t][i])
{
useif[i]=true;
if(link[i]==-1 || can(link[i]))
{
link[i]=t;
return true;
}
}
}
return false;
}
int maxMatch()
{
int num=0;
memset(link,0xff,sizeof(link)); //未连的计为-1
for(int i=1;i<=rNum;i++) //从右边点(女生)出发依次寻找增广路径
{
memset(useif,false,sizeof(useif));
if(can(i)) num++;
}
return num;
}
int main()
{
while(cin>>k,k)
{
cin>>rNum>>lNum;
getMap();
cout<<maxMatch()<<endl;
}
return 0;
}