http://acm.hdu.edu.cn/showproblem.php?pid=1083
题目大意:有P个课程和N个学生,现题目要求两点:
1. every student in the committee represents a different course (a student can represent a course if he/she visits that course)
2. each course has a representative in the committee
现想组建一个委员会,委员会中的每个学生都要代表不同的课程,且每个课程都有它的代表。
算法分析:这正符合二分图最大匹配的条件。把课程作为二分图中X节点集合,得到最大匹配,如果匹配数等于课程数,则匹配与Y集合的交集,就可看成是这样一个委员会,则输出YES,否则,输出NO。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<stdio.h>
#include<string.h>
int P, N;
int cnt[102]; //cnt[i] 记录的是学过课程i的学生个数
int list[102][302]; //list[i][j]表示学过课程i的第j个学生的编号
int visy[302]; //用来记录二分图中Y集合中的点时候被访问过
int link[302]; //link[i] 表示当前学生编号为i的匹配课程
int can(int t)
{
int i, k;
for (i = 1; i <= cnt[t]; i++){
k = list[t][i];
if (!visy[k]){
visy[k] = 1;
if (link[k] == -1 || can(link[k])){
link[k] = t;
return 1;
}
}
}
return 0;
}
int MaxMatch()
{
int i;
memset(link, -1, sizeof(link));
for (i = 1; i <= P; i++){
memset(visy, 0, sizeof(visy));
if (!can(i))
return 0;
}
return 1;
}
int main()
{
int T, i, j, flag;
scanf("%d", &T);
while (T--){
scanf("%d%d", &P, &N);
for (i = 1; i <= P; i++){
scanf("%d", &cnt[i]);
for (j = 1; j <= cnt[i]; j++){
scanf("%d", &list[i][j]);
}
}
flag = MaxMatch();
if (flag) puts("YES");
else puts("NO");
}
return 0;
}