题目http://acm.hdu.edu.cn/showproblem.php?pid=1083
描述:有p门的课,每门课都有若干学生,现在要为每个课程分配一名课代表,每个学生只能担任一门课的课代表,如果每个课都能找到课代表,则输出"YES",否则"NO"。
思想:采用二分图的最大匹配,对课程—学生关系建立一个图,进行二分图的最大匹配,如果最大匹配数==课程数,说明能够满足要求,否则不能。每个课程轮流选择课代表,从头遍历n学生,如果该学生还未担任任何课程的课代表或者一个学生担任的课代表的那个课程可以有其他人来担任课代表,那么该课程的课代表就是他了。用递归,不断进行匹配。保证最大匹配。
实现代码:
#include<iostream> using namespace std; int cs[305][305];//课程与学生的关心,cs[i][j]为1时表示j有选第i个课程。 int link[305];//表示学生担任课代表的课程。link[i]=j表示j课程的课代表是i bool has[305];//表示学生是否被考虑过能不能当某个课的课代表。 int p,n; //分配x课程的课代表 int fenpei(int x) { int i; for(i=1;i<=n;i++) { //如果i学生还没有担任课代表而且他有选x这个课。 if(!has[i]&&cs[x][i]==1) { has[i]=1; //i还未担任某个课程的课代表或者其担任的课代表还可以找到别人担任。 if(!link[i]||fenpei(link[i])) { link[i]=x; return 1; } } } return 0; } int main(int argc, char* argv[]) { int i,t,x,sum,m; cin>>t; while(t--) { cin>>p>>n; memset(cs,0,sizeof(cs)); for(i=1;i<=p;i++) { cin>>m; while(m--) { cin>>x; cs[i][x]=1; } } sum=0; memset(link,0,sizeof(link)); //为每个课程分配课代表 for(i=1;i<=p;i++) { //每次为一个课程选择课代表的时候,每个学生都要从头考虑,直到找到合适的课代表为止。 memset(has,0,sizeof(has)); if(fenpei(i)) sum++; } if(sum==p) cout<<"YES"<<endl; else cout<<"NO"<<endl; } return 0; }