6 3 3 1 1 1 2 1 3 2 1 2 3 3 1 0
3
这是一道非常非常经典的二分图匹配的题目.
这个二分匹配的题也可以理解为你是一位月老,一点一点的,通过寻找增广路来凑成一对又一对.
最大二分匹配的思路核心很简单:
无脑枚举,寻找最优解.
不断的通过枚举寻找增广路~
比如这个题目的思路就靠两个for循环构成题目的核心:
第一个for:
int output=0;//当然是输出的结果啦~ for(int i=1;i<=n;i++)//这里n表示男生的人数.(男生一般脸皮都比较厚所以要男生主动去问女生啦~(其实都可以)). { memset(vis,0,sizeof(vis)); if(find(i))//派每一个男生去找他喜欢的女孩纸~~~~~~~~~如果找到了能够同意他的女孩纸~~~~就算是筹上了一对~~~~~~ output++; }然后是第二个for
int find(int x) { for(int i=1;i<=m;i++)//有这么m个小姑娘小伙子需要去询问(一旦找到了能和自己凑成一对的小姑娘就停.) { if(vis[i]==0&&map[i][x])//如果当前小姑娘没有询问过(你要是询问两次人家小姑娘嫌你烦你造吧~~~~).并且这个小姑娘能同意了的情况下. { vis[i]=1; if(pri[i]==-1||find(pri[i]))//如果这个小姑娘没有其他男生曾过来和她约,或者是她约了其他小伙子但是还能让她约了的这个小伙子找到其他小姑娘. { pri[i]=x;//这个小伙子就算是和这个小姑娘搭上爱之桥了(谁知道会不会有后来人把这个小伙子赶跑.....)(可怜的一群屌丝.....) return 1; } } } return 0; }
这样子我们就欢欢喜喜的让最多组的男生和女生约在一起咯~~~~~~~
然后
这里贴上AC代码;
#include<stdio.h> #include<string.h> using namespace std; const int maxn = 505; int map[maxn][maxn]; //图的数组. int vis[maxn]; //标记数组. int pri[maxn]; int k,m,n; int find(int x) { for(int i=1;i<=m;i++) { if(vis[i]==0&&map[i][x]) { vis[i]=1; if(pri[i]==-1||find(pri[i])) { pri[i]=x; return 1; } } } return 0; } int main() { while(~scanf("%d",&k)) { if(k==0)break; scanf ("%d%d", &m, &n); memset (map, 0, sizeof (map)); memset (pri, -1, sizeof (pri)); for(int i=0;i<k;i++) { int a,b; scanf("%d%d",&a,&b); map[a][b]=1; } int output=0; for(int i=1;i<=n;i++) { memset(vis,0,sizeof(vis)); if(find(i)) output++; } printf("%d\n",output); } }