POJ -2289 -Jamie's Contact Groups (二分图多重匹配)

来源:互联网 发布:c语言中文网vip百度云 编辑:程序博客网 时间:2024/05/16 00:28

这道题是一道二分图多重匹配


题意:

XXX很受欢迎,手机里好友很多,现在想把好友分组,为了好找,每个好友只能加入一个组,并且要让每个组尽量的人数尽量小(某些人可以分到多个组内),问:最多人的组有多少人?


二分匹配是一个对应一个,就好如老师选课问题,一位老师只能教一门课!!

而这道题一位老师可以教n门课,为了不让老师过劳猝死,求每位老师最少教课数



原来的二分匹配已经不行了!!!

新的匹配已经出现


开一个数组  Vlink  表示第i个人进入的分组


再开一个二维数组link表示第i个分组的里面所有好友


新的匹配也很好理解,在原来的基础上只是多加了个link数组


对于每一次的匹配,判断一下是否可以匹配,相当于普通二分匹配的vlink[i]是否为0


然后把这个分组的所有的点都找一遍,看有没有增广路


或者说看看这个人是否可以移到别的分组里面,这样就保证了每个分组都尽量的留有位置


然后下次再匹配到这个组,可以把这个人加进来,如果加不进来,就说明匹配不成功!!


#include<string.h>#include<stdio.h>using namespace std;const int N = 1000+10;const int M = 500+10;int n,m;int e[N][M];int vlink[M];   //Vlink  其实就是match,但是储存的值为这个点匹配了多少个点(因为一个点可以对应匹配很多点)int link[M][N]; //此时link就是用来储存m点的所有匹配点int max_cap;bool vis[M];int path(int s){    for(int i=0;i<m;i++)    {        if(e[s][i] && !vis[i]) //如果这条路可以通        {            vis[i]=true;            if(vlink[i]<max_cap)  //并且i这个点匹配的数量没有达到最大值            {                link[i][vlink[i]++]=s;//那么把这个点放进去                return 1;            }            for(int j=0;j<vlink[i];j++)//对于i匹配到的每一个点            {                if(path(link[i][j]))//如果这点可以移到别的点                {                    link[i][j]=s;  //那么久进行移动                    return 1;                }            }        }    }    return 0;}bool max_match(int mid){    max_cap=mid;    memset(vlink,0,sizeof(vlink));    for(int i=0;i<n;i++)    {        memset(vis,false,sizeof(vis));        if(!path(i))            return false;    }    return true;}int main(){    char str[20],c;    int a;    while(scanf("%d %d",&n,&m)==2 && (n||m))    {        memset(e,false,sizeof(e));        for(int i=0;i<n;i++)  //输入        {            scanf("%s",str);            while(true)  //每输入一个数,读取后面的字符,如果是换行符,表示这组数据输入完成            {                scanf("%d%c",&a,&c);                e[i][a]=true;                if(c=='\n') break;            }        }        int left=1,right=n,ans=n;        while(left<=right)        {            int mid=(left+right)>>1;            if(max_match(mid))            {                if(mid<ans)                    ans=mid;                right=mid-1;            }            else left=mid+1;        }        printf("%d\n",ans);    }    return 0;}


 

阅读全文
0 0