现在的位置: 首页 > 综合 > 正文

poj 2289 Jamie’s Contact Groups 二分图多重匹配

2013年08月15日 ⁄ 综合 ⁄ 共 1386字 ⁄ 字号 评论关闭

题目 http://poj.org/problem?id=2289

这是我做的第一个 多重匹配   所以参考哦  别人代码   感觉不错

http://www.cnblogs.com/-sunshine/archive/2012/08/30/2664310.html

其实这个多重匹配有点像匈牙利算法   思想是一样的  

题意:给定一个规模为n的名单,要将名单中的人归到m个组中,给出每个人可能的分组号,需要确定一种分配方案,是的最大规模的组最小。

思路:一对多的二分图的多重匹配。二分图的多重匹配算法的实现类似于匈牙利算法,对于集合C中的元素xi,找到一个与其相连的元素yi后,检查匈牙利算法的两个条件是否成立,若yi未被匹配,则将
xi,yi匹配。否则,如果与yi匹配的元素已经达到上限,那么在所有与yi匹配的元素中选择一个元素,检查是否能找到一条增广路径,如果能,则让出位置,让xi与yi匹配。
二分求出limit,知道找到可以构成多重匹配的最小限制limit,在main函数中二分搜索。

ac代码

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define max 2001

bool map[max][max];
bool mark[max];
int link[max];
int cy[max][max];
int n,m,mid;   //n表示列表长度  m表示分配组数

bool findpath(int u)
{
    int i,j;
    for(i=0;i<m;i++)
    {
        if(map[u][i]&&!mark[i])
        {
            mark[i]=1;
            if(link[i]<mid)
            {
                cy[i][link[i]++]=u;
                return true;
            }
            for(j=0;j<link[i];j++)
            {
               if(findpath(cy[i][j]))
               {
                   cy[i][j]=u;
                   return true;
               }
            }
        }
    }
    return false;
}

bool maxmatch()
{
    int i,j;
    memset(link,0,sizeof(link));
    for(i=0;i<n;i++)
    {
        memset(mark,false,sizeof(mark));
        if(!findpath(i)) return false;

    }
    return true;
}

int main()
{
    int i,j,v;
    char len[1020];
    while(cin>>n>>m,n+m)
    {
        getchar();
        memset(map,false,sizeof(map));
       // memset(link,false,sizeof(link));

        for(i=0;i<n;i++)
        {
           cin.getline(len,1020);
           int k=strlen(len);

           for(j=0;j<=k;j++)
           {
               if(len[j]>='0'&&len[j]<='9')
               {
                     v=0;
                     while(len[j]>='0'&&len[j]<='9')
                     {
                         v=v*10+len[j++]-'0';
                     }
                     map[i][v]=1;
               }
           }
        }
        int left=0,right=n;
        while(left<right)
        {
            mid=(left+right)/2;
            if(maxmatch()) right=mid;
            else left=mid+1;
        }

        cout<<right<<endl;
    }
    return 0;
}

 

抱歉!评论已关闭.