• hdu1669+二分多重匹配+二分


    n个人分成m组,求人数最多的那一组人数的最小值。

    每个人肯定只能匹配一个组,但一个组可以匹配多个人,因此属于多重匹配。

    我们设置一个limit,表示每组最多能容纳的人数。在dfs(u)寻找u的匹配时,如果某一组vv的人数小于limit,那么可以把u和vv匹配,vv已经匹配的人数+1。否则,当人数已经达到limit,我们对vv的每个匹配做dfs,即寻找增广,若能找到,修改这个匹配,即让vv和u匹配。

    然后我们可以二分limit,当u集合(人的集合)中所有点都能找到匹配,则减小limit值,否则只要有一个点找不到匹配,增大limit值。

    多重匹配和二分匹配匈牙利算法的写法类似,只不过加了一个cnt数组表示v已经匹配到的人数,linker数组也增加了一维。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<vector>
     4 using namespace std;
     5 int n,m;
     6 vector<int> v[1100];
     7 int linker[1100][1100],vis[1100],cnt[1100];
     8 int limit;
     9 bool dfs(int u)
    10 {
    11     int i,j;
    12     for(i=0;i<v[u].size();i++)
    13     {
    14         int vv=v[u][i];
    15         if(!vis[vv])
    16         {
    17             vis[vv]=1;
    18             if(cnt[vv]<limit)
    19             {
    20                 linker[vv][cnt[vv]++]=u;
    21                 return true;
    22             }
    23             else
    24             {
    25                 for(j=0;j<cnt[vv];j++)
    26                 {
    27                     if(dfs(linker[vv][j]))
    28                     {
    29                         linker[vv][j]=u;
    30                         return true;
    31                     }
    32                 }
    33             }
    34         }
    35     }
    36     return false;
    37 }
    38 int main()
    39 {
    40     int i,j;
    41     char str[110000];
    42     while(scanf("%d%d",&n,&m)!=EOF)
    43     {
    44         getchar();
    45         if(n==0&&m==0) break;
    46         for(i=0;i<n;i++)
    47             v[i].clear();
    48         for(i=0;i<n;i++)
    49         {
    50             gets(str);
    51             int len=strlen(str);
    52             j=0;
    53             loop:for(;j<len;j++)
    54             {
    55                 if(str[j]>='0'&&str[j]<='9')
    56                     break;
    57             }
    58             int num=0;
    59             bool judge=false;
    60             for(;j<len;j++)
    61             {
    62                 if(str[j]>='0'&&str[j]<='9')
    63                 {
    64                     judge=true;
    65                     num=num*10+(str[j]-'0');
    66                 }
    67                 else break;
    68             }
    69             if(judge) v[i].push_back(num);
    70             if(j<len) goto loop;
    71         }
    72         int l=0,r=n;
    73         while(l<r)
    74         {
    75             limit=(l+r)/2;
    76             memset(cnt,0,sizeof(cnt));
    77             for(i=0;i<n;i++)
    78             {
    79                 memset(vis,0,sizeof(vis));
    80                 if(!dfs(i)) break;
    81             }
    82             if(i>=n) r=limit;
    83             else l=limit+1;
    84         }
    85         printf("%d
    ",l);
    86     }
    87     return 0;
    88 }
  • 相关阅读:
    利用CSS计数函数counter()实现计数
    弹跳加载动画特效Bouncing loader
    HTML页面中解决内容元素随窗口变化布局变乱问题
    CSS中列表项list样式
    框模型中设置内容区域元素占地尺寸box-sizing属性
    PHP100视频教程-->视频下载
    HTML页面中5种超酷的伪类选择器:hover效果
    HTML中获取input中单选按钮radio数据(性别例子)
    HTML中 DOM操作的Document 对象详解(收藏)
    14、输入一个链表,从尾到头打印链表每个节点的值。
  • 原文地址:https://www.cnblogs.com/mt522/p/5372791.html
Copyright © 2020-2023  润新知