题目很水。主要是转化为最大二分匹配。题目中说了。总共了P门课,而要求选出含有P个学生的团队,要求这个团队中每个学生的选课不相同,且P门课要都有人选。也就是说一个人对应一门课了。P个不同的人对应P个不同的课。其实就是最大二分匹配。由于课程只有P个,故最大二分匹配最大为P,此题就是判断是否满足最大二分匹配为P。
下面是代码:200K+610MS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define fmax 110
#define smax 310
int pre[fmax];
bool vis[fmax];
bool match[smax][fmax];
int p,n,Case;
bool find(int x){
for(int i=1;i<=p;i++){
if(!vis[i] && match[x][i]){
vis[i]=true;
if(pre[i]==-1 || find(pre[i])){
pre[i]=x;
return true;
}
}
}
return false;
}
int main(){
scanf("%d",&Case);
while(Case--){
scanf("%d%d",&p,&n);
memset(pre,-1,sizeof(pre));
memset(match,0,sizeof(match));
for(int i=1;i<=p;i++){
int num,pivot;
scanf("%d",&num);
while(num--){
scanf("%d",&pivot);
match[pivot][i]=true;
}
}
int ans=0;
for(int i=1;i<=n;i++){
memset(vis,0,sizeof(vis));
ans+=find(i);
}
if(ans==p)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
下面是另一种形式的代码:200K+438MS(从这里可以看出当n与m相差较大时,以小值作为外层循环应该较为有利,当然是针对一般情况)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define fmax 310
#define smax 110
int pre[fmax];
bool vis[fmax];
bool match[smax][fmax];
int p,n,Case;
bool find(int x){
for(int i=1;i<=n;i++){
if(!vis[i] && match[x][i]){
vis[i]=true;
if(pre[i]==-1 || find(pre[i])){
pre[i]=x;
return true;
}
}
}
return false;
}
int main(){
scanf("%d",&Case);
while(Case--){
scanf("%d%d",&p,&n);
memset(pre,-1,sizeof(pre));
memset(match,0,sizeof(match));
for(int i=1;i<=p;i++){
int num,pivot;
scanf("%d",&num);
while(num--){
scanf("%d",&pivot);
match[i][pivot]=true;
}
}
int ans=0;
for(int i=1;i<=p;i++){
memset(vis,0,sizeof(vis));
ans+=find(i);
}
if(ans==p)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}