poj 2289 二分+多重匹配

最大值最小的一个常用方法是二分。二分“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\n", lb);
115     }
116     return 0;
117 }

 

posted @ 2015-08-23 12:24  hxy_has_been_used  阅读(148)  评论(0编辑  收藏  举报