题意:有p个课程,n个学生,告诉你每个课程有那些学生选,问是否可以找到一个正好有p个学生的集合使得集合里每个学生都作为一个课的代表且每个课的代表都互不相同。
解法:二分图匹配。如果匹配数是p,则答案可以,否则不可以。
代码:
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<math.h>
#include<limits.h>
#include<time.h>
#include<stdlib.h>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#include<iomanip>
#define LL long long
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
using namespace std;
const int MAXN = 305;
int n, p;
vector<int> g[MAXN];
int from[MAXN], tot;
bool use[MAXN];
bool match(int x)
{
for(int i = 0; i < g[x].size(); ++i)
if(!use[g[x][i]])
{
use[g[x][i]] = true;
if(from[g[x][i]] == -1 || match(from[g[x][i]]))
{
from[g[x][i]] = x;
return true;
}
}
return false;
}
int hungary()
{
tot = 0;
memset(from, -1, sizeof from);
for(int i = 1; i <= p; ++i)
{
memset(use, 0, sizeof use);
if(match(i)) ++tot;
}
return tot;
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
scanf("%d%d", &p, &n);
for(int i = 1; i < MAXN; i++) g[i].clear();
for(int i = 0; i < p; i++)
{
int m;
scanf("%d", &m);
while(m--)
{
int x;
scanf("%d", &x);
g[i + 1].push_back(x);
}
}
int res = hungary();
if(res == p) puts("YES");
else puts("NO");
}
return 0;
}