• POJ 3189 Steady Cow Assignment 【二分】+【多重匹配】


    <题目链接>

    题目大意:

    有n头牛,m个牛棚,每个牛棚都有一定的容量(就是最多能装多少只牛),然后每只牛对每个牛棚的喜好度不同(就是所有牛圈在每个牛心中都有一个排名),然后要求所有的牛都进牛棚,牛棚在牛心中的排名差计算方法为:所有牛中最大排名和最小排名之差+1(包括区间端点)。问最小的排名差。

    解题分析:

    先进行二分答案,二分枚举该区间等级的差值,然后根据枚举的区间差值找到所有的等级区间,判断这些等级区间中是否存在符合条件的。判断的依据就是个根据枚举的等级区间,对所有的牛和牛棚进行多重匹配,如果所有的牛都能够分配到牛棚中,则当前枚举的区间符合条件。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 const int N = 1e3+10;
     7 struct Node{
     8     int k,a[N];  //k代表牛棚当前的人数,a[N]存储牛棚中的所有人
     9 }match[N];
    10 int n,B,vis[N];
    11 int G[N][N],capacity[N];   
    12 bool dfs(int u,int l,int r){
    13     for(int i=1;i<=B;i++){
    14         if(!vis[i]&&G[u][i]>=l&&G[u][i]<=r){   //判断第i个牛棚在牛u心中的等级是否处于枚举的等级中
    15             vis[i]=1;
    16             if(match[i].k<capacity[i]){   //如果该牛棚未满,则将牛u(暂时)分配到牛棚i中
    17                 match[i].a[++match[i].k]=u;
    18                 return true;
    19             }
    20             for(int j=1;j<=match[i].k;j++){   
    21                 if(dfs(match[i].a[j],l,r)){   //如果该牛棚已满,就枚举该牛棚中所有的牛,看他们是否能够找到其他能够分配的牛棚
    22                     match[i].a[j]=u;   //如果能够找到的话,就用牛u来替代该牛的位置
    23                     return true;
    24                 }
    25             }
    26         }
    27     }
    28     return false;
    29 }
    30 bool Hungary(int l,int r){
    31     memset(match,0,sizeof(match));
    32     for(int i=1;i<=n;i++){
    33         memset(vis,0,sizeof(vis));
    34         if(!dfs(i,l,r))return false;    //只要有一只牛在当前枚举的区间内不能分配到牛棚中,就说明当前枚举的区间不合法
    35     }
    36     return true;
    37 }
    38 int main(){
    39     while(scanf("%d%d",&n,&B)!=EOF){
    40         memset(G,0,sizeof(G));
    41         for(int i=1;i<=n;i++)
    42             for(int j=1;j<=B;j++){
    43                 int x;scanf("%d",&x);
    44                 G[i][x]=j;    //第i头牛,对x牛棚的喜欢度是第j个等级
    45             }
    46         for(int i=1;i<=B;i++)
    47             scanf("%d",&capacity[i]);   //每个牛棚的容量
    48         int l=0,r=B,ans=B;
    49         while(l<=r){
    50             int mid=(l+r)>>1;   //枚举区间最大等级与最小等级的差值
    51             bool fp=false;
    52             for(int i=1;i<=B;i++){   //枚举区间的左端点,即该区间的最小等级
    53                 if(Hungary(i,i+mid)){   //判断在该等级范围内,是否满足条件
    54                     fp=true;break;
    55                 }
    56             }
    57             if(fp)ans=mid+1,r=mid-1;    //ans记录的是该区间的大小,所以需要+1
    58             else l=mid+1;
    59         }
    60         printf("%d
    ",ans);
    61     }
    62 }

    2018-11-17

  • 相关阅读:
    一台服务器Nginx配置多个域名(一级域名或二级)
    Nginx启动和停止
    git删除本地及远程分支
    纯js实现复制内容到剪切板
    js 实现字符串转日期进行比较大小
    git 本地分支与远程分支 新建/删除/合并
    设置Git 记住密码
    炒鸡简单的javaScript的call和apply方法
    如何打war包
    Git 查看远程分支、本地分支、删除本地分支及远程分支
  • 原文地址:https://www.cnblogs.com/00isok/p/9974246.html
Copyright © 2020-2023  润新知