#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
//const int max=100;
#define max 305
int P,N;
int map[max][max],match[max],used[max];
bool find (int x){
for (int i=1;i<=P;i++){
if (!used[i] && map[i][x]){
used[i] = true;
if (match[i] == -1 || find (match[i])){
match[i] = x;
return true;
}
}
}
return false;
}
int main (){
int t,stu,tmp;
cin >> t;
while (t--){
memset (map,0,sizeof (map));
memset (match,-1,sizeof (match));
cin >> P >> N;
int cnt=0;
for (int k= 1 ; k <= P; k++){
cin >> tmp;
for (int i=1;i<=tmp;i++){
scanf ("%d",&stu);
map[k][stu]=1;
}
}
for (int i=1;i<=N;i++){
memset (used,0,sizeof (used));
if (find (i))
cnt ++;
}
// cout<< cnt<<endl;
if (cnt == P)
puts ("YES");
else
puts ("NO");
}
return 0;
}
题目http://acm.hdu.edu.cn/showproblem.php?pid=1083
描述:有p门的课,每门课都有若干学生,现在要为每个课程分配一名课代表,每个学生只能担任一门课的课代表,如果每个课都能找到课代表,则输出"YES",否则"NO"。
思想:采用二分图的最大匹配,对课程—学生关系建立一个图,进行二分图的最大匹配,如果最大匹配数==课程数,说明能够满足要求,否则不能。每个课程轮流选择课代表,从头遍历n学生,如果该学生还未担任任何课程的课代表或者一个学生担任的课代表的那个课程可以有其他人来担任课代表,那么该课程的课代表就是他了。用递归,不断进行匹配。保证最大匹配。