POJ 2289 - Jamie's Contact Groups 二分+二分图的多重匹配

                题意:

                          要给通讯录分组..每个人只能分到其特定的分组之一..问能使最大的分组最小为多少..

                题解:

                          开始题目看错了..看成要使最大的分组很最小的分组差值最小..然后跪了...

                          按题目这个意思还是很简单的...二分枚举容量..然后做二分图的多重匹配判断...


Program:

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<cmath>
#include<stack>
#include<string.h>
#include<queue>
#define ll long long
#define esp 1e-5
#define MAXN 1006
#define MAXM 5000000
#define oo 100000007
using namespace std;
int n,m,num[MAXN],line[MAXN][MAXN];
bool g[MAXN][MAXN],used[MAXN];
bool dfs(int x,int C)
{
       for (int i=1;i<=m;i++)
          if (g[x][i] && !used[i])
          {
                  used[i]=true;
                  if (num[i]<C)
                  {
                        line[i][++num[i]]=x;
                        return true;
                  }
                  for (int j=1;j<=num[i];j++)
                     if (dfs(line[i][j],C))
                     {
                             line[i][j]=x;
                             return true;
                     }
          }
       return false;
}
bool getmax(int C)
{
       memset(num,0,sizeof(num));
       for (int i=1;i<=n;i++)
       {
              memset(used,false,sizeof(used));
              if (!dfs(i,C)) return false;
       }       
       return true;
}
int main()  
{           
       int i,x;
       char c; 
       while (~scanf("%d%d",&n,&m) && n)
       {   
               memset(g,false,sizeof(g));
               for (i=1;i<=n;i++) 
               {
                      do { c=getchar(); }while (c<'0' || c>'9');
                      while (1)
                      {
                             x=0;
                             while (c>='0' && c<='9')
                             {
                                    x=x*10+c-'0';
                                    c=getchar();
                             }
                             g[i][x+1]=true;
                             if (c=='\n') break;  
                             do { c=getchar(); }while (c==' ');
                             if (c=='\n') break;                         
                      }                      
               }
               int l=0,r=1005,mid; 
               while (r-l>1)
               {
                       mid=r+l>>1;
                       if (!getmax(mid)) l=mid;
                                    else r=mid;
               }
               printf("%d\n",r);
       }
       return 0;  
}  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值