POJ 2289 多重二分匹配+二分 模板

题意:在通讯录中有N个人,每个人能可能属于多个group,现要将这些人分组m组,设各组中的最大人数为max,求出该最小的最大值

下面用的是朴素的查找,核心代码find_path复杂度是VE的,不过据说可以用DINIC跑二分图可以得到sqrt(v)*E的

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <algorithm>
#include <set>
using namespace std;
typedef long long ll;
typedef unsigned long long Ull;
#define MM(a,b) memset(a,b,sizeof(a));
const double eps = 1e-10;
const int  inf =0x7f7f7f7f;
const double pi=acos(-1);
const int maxn=100000;

int n,m,k;
int mp[1005][505],link[505][1005],num[505],vis[505];
char s[20],c;

bool find_path(int u,int mid)
{
      for(int v=0;v<m;v++)
        if(mp[u][v]&&!vis[v])
        {
          vis[v]=1;
          if(num[v]<mid)
             {
               link[v][++num[v]]=u;
                 return true;
             }
          for(int i=1;i<=num[v];i++)
                if(find_path(link[v][i],mid))
                {
                   link[v][i]=u;
                   return true;
                }
          //vis[v]=0;这个地方不能将vis[v]清0,否则将多次重复计算,从而超时
//事实上只要右边的点检查过一次无法再匹配了,以后就都不行了 } return false; } bool ok(int mid) { MM(link,0); MM(num,0); for(int u=0;u<n;u++) { MM(vis,0); if(!find_path(u,mid)) return false; } return true; } int main() { while(~scanf("%d %d",&n,&m)&&(n||m)) { MM(mp,0); for(int i=0;i<n;i++) { scanf("%s",s); while(~scanf("%c",&c)) { if(c=='\n') break; scanf("%d",&k); mp[i][k]=1; } } int l=-1,r=n+1; while(r-l>1) { int mid=(l+r)>>1; if(ok(mid)) r=mid; else l=mid; } printf("%d\n",r); } return 0; }

  

posted @ 2016-05-09 14:17  快点说我帅  阅读(153)  评论(0编辑  收藏  举报