zoukankan      html  css  js  c++  java
  • 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;
    }
    为了更好的明天
  • 相关阅读:
    第二阶段站立会议03
    第二阶段站立会议02
    第二阶段站立会议01
    第十一周进度条
    小强大扫荡
    测试计划
    用户体验
    各组意见
    第一阶段绩效评估
    站立会议10
  • 原文地址:https://www.cnblogs.com/xiuwenli/p/9374550.html
Copyright © 2011-2022 走看看