Description
现在有$n$个囚笼,需要关押$m$个犯人,the big brother很担心囚笼的安全性,因为犯人都有自己的想法,他们只想住在特定的囚笼里面,那么big brother想知道最多 能关押多少个犯人,每个囚笼只能关押一个犯人,一个犯人也只能关押在一个囚笼里面。
Input
第一行 两个整数,$N (0 \leq N \leq 200)$ 和 $M (0 \leq M \leq 200)$ 。$N$ 是犯人的数量,$M$ 是囚笼的数量。
第二行到第$N+1$行 一共 $N$ 行,每行对应一只犯人。第一个数字 $(Si)$ 是这哥犯人愿意待的囚笼的数量 $(0 \leq Si \leq M)$。后面的$Si$个数表示这些囚笼的编号。
囚笼的编号限定在区间 $(1..M)$ 中,在同一行,一个囚笼不会被列出两次。
Output
只有一行。输出一个整数,表示最多能分配到的囚笼的数量.
Sample Input
5 5
1 1
1 2
1 3
1 4
1 5
Sample Output
5
二分图最大匹配模板
code:
#include <iostream>
#include <cstring>
#include <algorithm>
#define size 400
bool vis[size];
int x[size], y[size], Pair[size][size], nx, ny;
int path(int u)
{
for(int v=0;v<ny;v++){
if(Pair[u][v] && !vis[v]){
vis[v]=true;
if(y[v]==-1 || path(y[v]))
{
y[v]=u;
x[u]=v;
return 1;
}
}
}
return 0;
}
void maxMatch()
{
int ans=0;
memset(x, -1, sizeof(x));
memset(y, -1, sizeof(y));
for(int i=0;i<=nx;i++){
if(x[i]==-1){
memset(vis, false, sizeof(vis));
ans+=path(i);
}
}
printf("%d\n", ans);
}
using namespace std;
int main()
{
#ifdef OFFLINE
freopen("yi.txt", "r", stdin);
#endif
int s, c, i;
while(~scanf("%d %d", &nx, &ny)){
memset(Pair, 0, sizeof(Pair));
memset(vis, false, sizeof(vis));
for(i=0;i<nx;i++){
scanf("%d",&s);
while(s--){
scanf("%d",&c);
Pair[i][c-1]=1;
}
}
maxMatch();
}
return 0;
}