原题链接
题意
一共有N个学生跟P门课程,一个学生可以任意选一
门或多门课,问是否达成:
1.每个学生选的都是不同的课(即不能有两个学生选同一门课)
2.每门课都有一个代表(即P门课都被成功选过)
输入为:
P N(课程数跟学生数)
接着有P行,格式为Count studenti studenti+1 ……studentcount
(Count表示对课程1感兴趣的学生数,接着有Count个学生)
如第一行3 1 2 3表示学生1跟学生2跟学生3对课程1感兴趣
输出为:
若能满足上面两个要求这输出”YES”,否则为”NO”
思路
二分图匹配问题,匈牙利算法模板题。
#include <iostream>
#include <cstring>
using namespace std;
const int maxn=500;
int mat[maxn][maxn]; //存储二分图
int link[maxn]; //记录匹配
bool vis[maxn];
int nx,ny; //两个集合的元素个数
bool dfs(int u) //从课程u出发
{
for(int i = 1; i <= ny; i ++) //遍历每个学生
{
if(mat[u][i] && !vis[i]) //如果右边相连且学生没有被记录过
{
vis[i] = 1;
if(link[i] == -1 || dfs(link[i])) //寻找交错链
{
link[i] = u;
return true;
}
}
}
return false;
}
int hungary()
{
int ans = 0;
memset(link, -1, sizeof(link));//初始化,无匹配
for(int i = 1; i <= nx; i ++)
{
memset(vis, 0, sizeof(vis));
if(dfs(i))
ans ++;
}
return ans;
}
int main()
{
int t, i, j, x, n;
cin >> t;
while(t --)
{
memset(mat, 0, sizeof(mat));
cin >> nx >> ny; //nx为课程集合,ny为学生集合
for(i = 1; i <= nx; i++)
{
cin >> n;
for(j = 1; j <= n; j ++)
{
cin >> x;
mat[i][x] = 1; //学生x对课程i感兴趣,置1
}
}
int ans = hungary();//最大匹配数量
if(ans != nx)
cout << "NO" << endl;
else
cout << "YES" <<endl;
}
return 0;
}