题目大意:N个学生,p们课,,每一门课程可以有多个学生选修,给出每门课程学生的选修情况,问:对于每门课程可不可以找到一个课代表( 前提是该学生要选修该门课程)
二分图匹配:
只用在输入处理(即构造二分图时注意下就可以的)
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define MAXN 300+2
int g[MAXN][MAXN];
int cp[MAXN],cn[MAXN];
int mk[MAXN];
int p,n;
int path(int u) //DFS增广
{
for(int v=1;v<=n;v++) //遍历所有的学生
{
if(g[u][v] && !mk[v] ) //如果u与v邻接,即学生v选了课程u,且v未被访问过
{
mk[v]=1;
if(!cn[v] || path(cn[v]))//v未匹配,或从cy[v]出发可以找到增广路
{
cp[u]=v; //把v匹配给u
cn[v]=u; //把u匹配给v
return 1;
}
}
}
return 0;
}
int max_match() //求最大匹配
{
int res=0;
memset(cp,0,sizeof(cp));
memset(cn,0,sizeof(cn));
for(int i=1;i<=p;i++)
{
if(!cp[i]){ //从每个未盖点出发,寻求增广路
memset(mk,0,sizeof(mk));
res+=path(i);
}
}
return res;
}
int main()
{
int t,num,k;
scanf("%d",&t);
while(t--)
{
memset(g,0,sizeof(g));
scanf("%d%d",&p,&n);
for(int i=1;i<=p;i++)//课程标号从1-p
{
scanf("%d",&num);
while(num--)
{
scanf("%d",&k);
g[i][k]=1; //构造二分图
}
}
int flag=max_match();
if(flag==p)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}