poj 2289(二分图多重匹配+二分)

题意:一个人通讯录中好友有许多,然后需要分组,现在告诉你不同的的人能分进小组的编号,然后问你怎么分配是小组中人最多的人最少,输出最小值。

思路:二分答案然后判断是不是能完全匹配。比较简单细节看代码。

代码如下:

  1 /**************************************************
  2  * Author     : xiaohao Z
  3  * Blog     : http://www.cnblogs.com/shu-xiaohao/
  4  * Last modified : 2014-02-23 15:21
  5  * Filename     : t2.cpp
  6  * Description     : 
  7  * ************************************************/
  8 
  9 #include <iostream>
 10 #include <cstdio>
 11 #include <cstring>
 12 #include <cstdlib>
 13 #include <cmath>
 14 #include <algorithm>
 15 #include <queue>
 16 #include <stack>
 17 #include <vector>
 18 #include <set>
 19 #include <map>
 20 #define MP(a, b) make_pair(a, b)
 21 #define PB(a) push_back(a)
 22     
 23 using namespace std;
 24 typedef long long ll;
 25 typedef pair<int, int> pii;
 26 typedef pair<unsigned int,unsigned int> puu;
 27 typedef pair<int, double> pid;
 28 typedef pair<ll, int> pli;
 29 typedef pair<int, ll> pil;
 30 
 31 const int INF = 0x3f3f3f3f;
 32 const double eps = 1E-6;
 33 const int MAXN = 1010;
 34 const int MAXM = 510;
 35 int uN,vN;
 36 int g[MAXN][MAXM];
 37 int linker[MAXM][MAXN];
 38 bool used[MAXM];
 39 char name[1010][101];
 40 int num[MAXM];//右边最大的匹配数
 41 
 42 bool dfs(int u)
 43 {
 44     for(int v = 0; v < vN; v++)
 45         if(g[u][v] && !used[v])
 46         {
 47             used[v] = true;
 48             if(linker[v][0] < num[v])
 49             {
 50                 linker[v][++linker[v][0]] = u;
 51                 return true;
 52             }
 53             for(int i = 1; i <= num[0]; i++)
 54                 if(dfs(linker[v][i]))
 55                 {
 56                     linker[v][i] = u;
 57                     return true;
 58                 }
 59         }
 60     return false;
 61 }
 62 
 63 int hungary()
 64 {
 65     int res = 0;
 66     for(int i = 0; i < vN; i++)
 67         linker[i][0] = 0;
 68     for(int u = 0; u < uN; u++)
 69     {
 70         memset(used,false,sizeof(used));
 71         if(dfs(u))res++;
 72     }
 73     return res;
 74 }
 75 
 76 bool J(int m){
 77     for(int i=0; i<vN; i++) num[i] = m;
 78     int ret = hungary();
 79     if(ret == uN) return true;
 80     else return false;
 81 }
 82 
 83 int main()
 84 {
 85 //    freopen("in.txt", "r", stdin);
 86 
 87     int vex;
 88     while(scanf("%d%d", &uN, &vN)!=EOF){
 89         if(!uN && !vN) break;
 90         memset(g, 0, sizeof g);
 91         for(int i=0; i<uN; i++){
 92             scanf("%s", name[i]);
 93             while(getchar()!='
'){
 94                 scanf("%d", &vex);     
 95                 g[i][vex] = 1;
 96             }
 97         }
 98         int l = 0, r = uN;
 99         while(l < r){
100             int m = (l+r)/2;
101             if(J(m)) r = m;     
102             else l = m+1; 
103         }
104         printf("%d
", l);
105     }
106     return 0;
107 }
View Code
奔跑吧!少年!趁着你还年轻
原文地址:https://www.cnblogs.com/shu-xiaohao/p/3562230.html