最大值最小的一个常用方法是二分。二分“the size of the largest group”然后每次判断最大匹配数是否为人数即可。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <cctype> 5 using namespace std; 6 7 const int X = 1000; 8 const int Y = 500; 9 int head[X]; 10 int cnt[Y]; 11 int mark[Y][X]; 12 bool visit[Y]; 13 int n, m, e, sz; 14 15 void init() 16 { 17 e = 0; 18 memset( head, -1, sizeof(head) ); 19 } 20 21 struct Edge 22 { 23 int v, next; 24 } edge[X * Y]; 25 26 void addEdge( int u, int v ) 27 { 28 edge[e].v = v; 29 edge[e].next = head[u]; 30 head[u] = e++; 31 } 32 33 int dfs( int u ) 34 { 35 for ( int i = head[u]; i != -1; i = edge[i].next ) 36 { 37 int v = edge[i].v; 38 if ( !visit[v] ) 39 { 40 visit[v] = 1; 41 if ( cnt[v] < sz ) 42 { 43 mark[v][cnt[v]++] = u; 44 return 1; 45 } 46 else 47 { 48 for ( int j = 0; j < cnt[v]; j++ ) 49 { 50 if ( dfs( mark[v][j] ) ) 51 { 52 mark[v][j] = u; 53 return 1; 54 } 55 } 56 } 57 } 58 } 59 return 0; 60 } 61 62 bool hungary() 63 { 64 memset( cnt, 0, sizeof(cnt) ); 65 for ( int i = 0; i < n; i++ ) 66 { 67 memset( visit, 0, sizeof(visit) ); 68 if ( !dfs(i) ) return false; 69 } 70 return true; 71 } 72 73 const int L = 501; 74 char list[L]; 75 76 int main () 77 { 78 while ( scanf("%d%d", &n, &m) != EOF ) 79 { 80 if ( n == 0 && m == 0 ) break; 81 init(); 82 getchar(); 83 for ( int i = 0; i < n; i++ ) 84 { 85 gets(list); 86 int len = strlen(list); 87 int j = 0, ret; 88 while ( 1 ) 89 { 90 while ( !isdigit(list[j]) ) j++; 91 ret = 0; 92 while ( isdigit(list[j]) ) 93 { 94 ret = ret * 10 + list[j] - '0'; 95 j++; 96 } 97 addEdge( i, ret ); 98 if ( j == len ) break; 99 } 100 } 101 int lb = 1, ub = n; 102 while ( lb < ub ) 103 { 104 sz = ( lb + ub ) >> 1; 105 if ( hungary() ) 106 { 107 ub = sz; 108 } 109 else 110 { 111 lb = sz + 1; 112 } 113 } 114 printf("%d ", lb); 115 } 116 return 0; 117 }