这是一道经典的二分图和匈牙利算法的题目,所以有必要先了解一下这两个名词的概念
在了解了什么事匈牙利算法之后,下面在看着倒题就简单了,另外其他的此类题,只要是满足上面博客中所说的二分图的概念的就可以直接用模板了
具体算法:
#include <iostream> #include <stdio.h> #include <string.h> #include <math.h> #include <stdlib.h> using namespace std; int map[502][502]; bool visited[502]; //标记男生是否被访问 int match[502]; //标记是否已经和女生已经匹配了 //也就是说这两个都是男生具体情况的数组 int n,m; bool find(int i) //查找当前的i是否可以匹配 { int j; for(j=1;j<=n;j++) { if(map[i][j]&&!visited[j])//在这里很有必要说一下visited这个数组,因为在之后的递归中,就会把这个标记好了的对象默认为 //已经和上一次的对象匹配过了,这样就不会再访问这个对象了,这在好几个的连续递归中显得尤为重要 { visited[j]=1; if(match[j]==-1||find(match[j])) //在此次查找的时候其实如果已经匹配过了则会在调用的时候即使是已经匹配成功了,由于 //当时在匹配的时候已经对可以匹配成功的做了match的标记了,就会继续查找他的下一个 //能够匹配的对象 { match[j]=i; return 1; } } } return 0; } int main() { int k,i,x,y,ans; while(scanf("%d",&k)&&k) { ans=0; memset(map,0,sizeof(map)); memset(match,-1,sizeof(match)); scanf("%d%d",&m,&n); for(i=0;i<k;i++)//对有意思的进行初始化 { scanf("%d%d",&x,&y); map[x][y]=1; } for(i=1;i<=m;i++) { memset(visited,0,sizeof(visited));//开始标记为全部没有访问 if(find(i)) //查找当前的i是否可以匹配成功 ans++; } cout<<ans<<endl; } return 0; }