POJ

题意:N个人,M个团体。每个人有属于自己的一些团体编号。将每个人分配到自己属于的团体中,问这个人数最多的团体其人数最小值是多少。

分析:一个一对多的二分图匹配,且是最大值最小化问题。二分图的多重匹配建立在匈牙利算法的基础上,令每个Y部的点可匹配多个点,但是规定其上限,超过上限就要在已有的匹配点中寻找增广路。对于X部的点,只要有一个点没有被匹配,那么算法失败。以此二分确定答案,注意二分的姿势...

该题可做模板。

#include<iostream>
#include<stdio.h>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long LL;
const int maxn = 1e3+5,maxm = 5e5+5;
int N,M;
struct Node{
    int K[maxn];
}link[maxn];
int cnt[maxn];
struct Edge{
    int to,next;
}edges[maxm];
int head[maxn],tot;
int linker[maxn];
bool used[maxn];

void init()
{
    tot=0;
    memset(head,-1,sizeof(head));
}

void AddEdge(int u,int v)
{
    edges[tot].to = v;
    edges[tot].next = head[u];
    head[u] = tot++;
}

bool dfs(int u,int limit){
    int v;
    for(int i=head[u];~i;i = edges[i].next){
        v = edges[i].to;
        if(!used[v]){
            used[v]=true;
            if(cnt[v]<limit){
                link[v].K[cnt[v]++]=u;
                return true;
            }
            for(int j=0;j<cnt[v];++j){
                if(dfs(link[v].K[j],limit)){
                    link[v].K[j]=u;
                    return true;
                }
            }
        }
    }
    return false;
}

bool hungary(int limit){
    memset(cnt,0,sizeof(cnt));
    for(int u=1;u<=N;u++){
        memset(used,0,sizeof(used));
        if(!dfs(u,limit)) return false;     //只要有一个人不能匹配则失败
    }
    return true; 
}

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
    #endif
    int T,u,v,tmp,k;
    char c;
    while(scanf("%d%d",&N,&M)==2){
        if(!N) break;
        init();
        for(int u=1;u<=N;++u){
            char op[maxn];
            scanf("%s",op);
            while(true){
                scanf("%d%c",&v,&c);
                AddEdge(u,v+1);
                if(c == '
') break;
            }            
        }
        int L=1,R=N,mid,ans=N;
        while(L<=R){
            mid = (L+R)>>1;
            if(hungary(mid)){
                ans = mid;
                R = mid-1;
            }
            else L=mid+1; 
        }
        printf("%d
",ans);
    }
    return 0;
}
为了更好的明天
原文地址:https://www.cnblogs.com/xiuwenli/p/9374550.html