【codevs】2776寻找代表元
题目描述 Description
广州二中苏元实验学校一共有n个社团,分别用1到n编号。
广州二中苏元实验学校一共有m个人,分别用1到m编号。每个人可以参加一个或多个社团,也可以不参加任何社团。
每个社团都需要选一个代表。谦哥希望更多的人能够成为代表。
输入描述 Input Description
第一行输入两个数n和m。
以下n行每行若干个数,这些数都是不超过m的正整数。其中第i行的数表示社团i的全部成员。每行用一个0结束。
输出描述 Output Description
输出最多的能够成为代表的人数。
样例输入 Sample Input
4 4
1 2 0
1 2 0
1 2 0
1 2 3 4 0
样例输出 Sample Output
3
数据范围及提示 Data Size & Hint
各个测试点1s
数据范围
n,m<=200
(。・_・。)ノ裸的匈牙利算法,主要用的思想就是递归;
贴一下CSDN上一个介绍匈牙利算法的帖子,很容易理解
放上代码(σ`д′)σ
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 int n,m; 6 bool join[201][201];//join[i][j]记录j学生是否加入i社团; 7 bool v[201];//该学生是否已经判断过; 8 bool r[201];//该社团能否找到一个不重复的代表; 9 int stu[201];//记录学生代表的社团编号; 10 bool find(int x) 11 { 12 for(int i=1;i<=m;i++) 13 { 14 if(join[x][i]&&!v[i])//如果有学生加入该社团并且这个学生没有判断过(如果判断过的话没有必要再判断了) 15 { 16 v[i]=1; 17 if(stu[i]==0||find(stu[i]))//该学生之前代表的社团还能找到别的学生作为代表; 18 { 19 stu[i]=x; 20 return true; 21 } 22 } 23 } 24 return false; 25 } 26 int main() 27 { 28 scanf("%d%d",&n,&m); 29 memset(join,0,sizeof(join)); 30 for(int i=1;i<=n;i++) 31 { 32 int j=1; 33 while(j!=0) 34 { 35 scanf("%d",&j); 36 join[i][j]=1; 37 } 38 } 39 memset(stu,0,sizeof(stu)); 40 int ans=0; 41 for(int i=1;i<=n;i++) 42 { 43 memset(v,0,sizeof(v)); 44 r[i]=find(i); 45 if(r[i])//记录能找到的社团数量,即不重复的代表数量; 46 { 47 ans++; 48 } 49 } 50 printf("%d",ans); 51 return 0; 52 }