这是一道 二分图 求最大匹配边 最经典的例子,开始我竟没有看出来。。
题目大意是,给定N名学生,P名课程,一名学生可以修任意门课程,要问的是能否在N名学生中找到P个人使他们满足两个条件:每个学生代表一门不同的课程,每门课程由一名学生代表。
其实把这两句话 好好咀嚼一下,发现就是 二分图中最大匹配的问题。 匹配的概念是 每个顶点只能由一条边对应。当我们求出课程的最大匹配边数,其实就是求出了 committee里面的成员数目。 判断是否等于p,相应输出 YES,或者NO
本次关键运用 匈牙利算法。 注意求的是 课程的最大匹配边,所以开始的时候是从 课程p中 寻找增广路。
此题输入数字比较多,刚开始用cin超时了好几次,要用 scanf 和 printf
我网上查了下,两者速度上相差10倍左右,一个指名了输入的类型,一个还要用输入流判断类型,你说哪个快?
#include <iostream>
using namespace std;
#define P 110
#define N 310
int map[P][N];
int check[N];
bool visit[N];
int n,p;
bool dfs(int v){
int i;
for(i=1;i<=n;i++){
if(!visit[i]&&map[v][i]){
visit[i] = 1;
if(check[i]==-1||dfs(check[i])){
check[i] = v;
return true;
}
}
}
return false;
}
int hungry(){
int ans = 0;
memset(check,-1,sizeof(check));
for(int i=1;i<=p;i++){
memset(visit,0,sizeof(visit));
if(dfs(i))
ans++;
}
return ans;
}
int main(){
int T,i,j,num,stu;
scanf("%d",&T);
while(T--){
memset(map,0,sizeof(map));
scanf("%d %d",&p,&n);
for(i=1;i<=p;i++){
scanf("%d",&num);
for(j=0;j<num;j++){
scanf("%d",&stu);
map[i][stu] = 1;
}
}
if(hungry()==p)
printf("%s\n","YES");
else
printf("%s\n","NO");
}
return 0;
}