二分图——多重匹配模板hdu1669

好像多重匹配一般是用网络流来做的。。

这是匈牙利算法的模板:lim是每个组的上界

思路是每个组都可以匹配lim个点,那么当点x遇到的组匹配的点数还没有超过lim时,直接匹配即可

如果已经等于了lim,这时就要从这个组的lim个点里找到一个能匹配到其他组的点(类似于普通匹配的寻找增广路过程)

int dfs(int x,int lim){
    for(int i=1;i<=m;i++)//枚举每个组 
        if(!vis[i] && mp[x][i]){
            vis[i]=1;
            if(match[i].size()<lim){
                match[i].push_back(x);
                return 1;
            } 
            //每个和i匹配的点 
            for(int j=0;j<match[i].size();j++){
                if(dfs(match[i][j],lim)){
                    match[i][j]=x;
                    return 1; 
                } 
            } 
        }
    return 0;
}

完整代码

#include<bits/stdc++.h>
using namespace std;
#define N 2005
int n,m,mp[N][N],vis[N];
vector<int>match[N];

int dfs(int x,int lim){
    for(int i=1;i<=m;i++)//枚举每个组 
        if(!vis[i] && mp[x][i]){
            vis[i]=1;
            if(match[i].size()<lim){
                match[i].push_back(x);
                return 1;
            } 
            //每个和i匹配的点 
            for(int j=0;j<match[i].size();j++){
                if(dfs(match[i][j],lim)){
                    match[i][j]=x;
                    return 1; 
                } 
            } 
        }
    return 0;
}

int judge(int lim){
    for(int i=1;i<=n;i++)match[i].clear();
    for(int i=1;i<=n;i++){
        memset(vis,0,sizeof vis);
        if(!dfs(i,lim))return 0;
    } 
    return 1;
}

char s[N],ch;
int main(){
    while(cin>>n>>m,n){
        memset(mp,0,sizeof mp);
        for(int i=1;i<=n;i++){
            scanf("%s",s);
            int j;
            while(1){
                scanf("%d%c",&j,&ch);
                mp[i][++j]=1;
                if(ch=='\n')break;
            }
        }
        int l=0,r=2*n,mid,ans=0;
        while(l<=r){
            mid=l+r>>1;
            if(judge(mid))
                ans=mid,r=mid-1;
            else l=mid+1;
        }
        cout<<ans<<endl;
    }
}
View Code

猜你喜欢

转载自www.cnblogs.com/zsben991126/p/10888877.html