Description
Input
Output
Sample Input
3 2 John 0 1 Rose 1 Mary 1 5 4 ACM 1 2 3 ICPC 0 1 Asian 0 2 3 Regional 1 2 ShangHai 0 2 0 0
Sample Output
2 2
题目大意:给你n个人可能的分组,给你m个组。问你将n个人分到组中,且每个人只能分到一个组内,最大组(组内人数最多)的最小值是多少。
解题思路:多重匹配。这是一对多的情况。很明显是多重匹配,但是匹配次数却没有,而是让求的结果。那我们就枚举匹配次数。如果该匹配次数满足条件,记录答案,同时向小逼近,如果不满足,就向大逼近。
#include<stdio.h> #include<algorithm> #include<string.h> #include<vector> #include<iostream> using namespace std; const int maxn = 1010; int Map[maxn][maxn]; //linker[v][j]表示第j个与Y部的v匹配的是x部的谁 int linker[maxn][maxn], used[maxn]; int mid; bool dfs(int u,int rn){ for(int v = 1; v <= rn; v++){ if(used[v] || !Map[u][v]){ continue; } used[v] = 1; if(linker[v][0] < mid){ //枚举的匹配次数 linker[v][++linker[v][0]] = u; return true; }else{ for(int j = 1; j <= linker[v][0]; j++){ if(dfs(linker[v][j],rn)){ linker[v][j] = u; return true; } } } } return false; } bool Hungary(int ln,int rn){ int ret = 0; for(int i = 0; i <= rn; i++){ linker[i][0] = 0; } for(int i = 1; i <= ln; i++){ memset(used,0,sizeof(used)); if(dfs(i,rn)){ ret++; } } if(ln == ret){ return true; } return false; } int main(){ int n,m; char str[5000]; while(scanf("%d%d",&n,&m)!=EOF&&(n+m)){ memset(Map,0,sizeof(Map)); getchar(); for(int i = 1; i <= n; i++){ gets(str); int len = strlen(str); int v = 0, flag = 1; for(int j = 0; j <= len; j++){ if(str[j] >= ‘0‘&& str[j] <= ‘9‘){ v = v*10 + str[j]-‘0‘; flag = 0; }else{ if(flag) continue; else{ Map[i][v+1] = 1; v = 0; } } } } int l = 1, r = n; while(l < r){ mid = (l+r)/2; if(Hungary(n,m)){ r = mid; }else{ l = mid + 1; } } printf("%d\n",r); } return 0; }
POJ 2289——Jamie's Contact Groups——————【多重匹配、二分枚举匹配次数】
原文:http://www.cnblogs.com/chengsheng/p/4961210.html