【题目大意】(又是农夫约翰的奶牛,奶牛好跳啊!)背景太复杂直接讲输入输出好了:
input:第一行 两个整数,n(0<=n<=200)和m(0<=m<=200) 。n是奶牛数量,m是牛栏数量。
第二行 到 第n+1行 一共 n 行,每行对应一只奶牛。
第一个数字 (t) 是这头奶牛愿意在其中产奶的牛栏的数目(0<=t<=m) 。后面的t个数表示这些牛栏的编号。【牛栏的编号限定在区间 (1..m) 中】
output:牛与牛栏的最大匹配值
【分析】二分图匹配模板题,这里写的是匈牙利算法。
【负责任的Hans】什么是二分图匹配呢?就是两个集合相互可以有选择的匹配,但一个对一个,求出最大可匹配的值。匈牙利算法也很好理解,每次找到选择匹配的对象,只有两种状态:①未匹配,我们就匹配上它!;②已匹配,我们就dfs它,让它跟另外的对象匹配(把它逼走)。
【是不是还没有懂?好吧我承认自己太suo了】
贴代码!!!
【感悟】这次竟然不是夜深写博客~今天是YALI中学2016社团节开幕式~也祝今年我大YALI110岁生日快乐【是个老老人了呢23333】
其实此代码还是有点迷的地方:为什么把memset(p)放在循环里才能对啊?....怪我没有细究,回家睡觉时在慢慢想好了~
最后!Hans博客更名了!Free Hans跳动的函数哈哈哈哈哈哈【402完美队形】
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN (200+10)
#define MAXM (200+10)
int p[MAXN], f[MAXN];
int cow[MAXN][MAXM];
int n, m;
bool dfs(int x){
for(int i = 1; i <= m; i++){
if(cow[x][i] && !p[i]){
p[i] = 1;
if(f[i] == -1 || dfs(f[i])){
f[i] = x;
return true;
}
}
}
return false;
}
int main(){
while(scanf("%d%d", &n, &m) != EOF){
int ans = 0;
memset(cow, 0, sizeof(cow));
memset(f, -1, sizeof(f));
for(int i = 1; i <= n; i++){
int t, tot;
scanf("%d", &t);
while(t--){
scanf("%d", &tot);
cow[i][tot] = 1;
}
}
for(int i = 1; i <= n; i++){
memset(p, 0, sizeof(p));
if(dfs(i)) ans++;
}
printf("%d\n", ans);
}
return 0;
}