题目大意:给出N个学生登记对P种课程感兴趣的情况,一个学生可以选0、1...多门课,问能不能按规定形成一个有P个人的委员会,规定如下:委员会里的每个学生都代表一个不同的课程;每个课程都有一个课代表
输入:case个数
第i个case的课程数P 学生数N
第j个课程的学生个数Countj 学生号码...(学生号码一共Countj个,中间空格隔开)
输出:YES/NO
分析:二分图的最大匹配。最大匹配数=课程数 即可。这样就保证了一个课程匹配一个学生,而且不重复。
代码:转载自http://blog.csdn.net/u013899738/article/details/47275293
- #include <stdio.h>
- #include <string.h>
- #include <stack>
- #include <queue>
- #include <set>
- #include <map>
- #define N 1000
- using namespace std;
- int n,p,lin[N],cnt;//lin[i]:第个course相连的student
- bool mp[N][N],used[N];
- bool searc(int a){//判断是否能构成新的增广序列的函数
- for(int j=1;j<=n;j++)
- if(mp[a][j]&&!used[j]){//连通且没用过
- used[j]=1;
- if(lin[j]==-1 || searc(lin[j])){//无配对或构成增广序列
- lin[j]=a;
- return true;
- }
- }//if
- return false;
- }
- int main(){
- int T,num,temp;
- scanf("%d",&T);
- while(T--){
- scanf("%d%d",&p,&n);
- cnt=0;
- memset(mp,0,sizeof(mp));
- memset(lin,-1,sizeof(lin));
- for(int i=1;i<=p;i++){
- scanf("%d",&num);
- for(int j=1;j<=num;j++){
- scanf("%d",&temp);
- mp[i][temp]=true;
- }//for_j
- }//for_i
- //匈牙利算法
- for(int i=1;i<=p;i++){
- memset(used,0,sizeof(used));
- if(searc(i)) cnt++;
- }
- if(p==cnt) printf("YES\n");
- else printf("NO\n");
- }//while
- return 0;
- }