zoukankan      html  css  js  c++  java
  • Hrbust-1492 盒子(二分图最大匹配)

    这里写图片描述
    二分图模板题。
    输入N表示盒子总数,M表示关系数
    接下来M行表示A盒子可以放在B盒子内部,也就是说盒子谁放在谁里的关系是一对一的。
    既然要求放在外面的盒子最少,那么就应该尽量使每个盒子都尽量找到一个比自己大的并且放进去。
    又因为不能有超过两个盒子并列放在一个盒子内部,也就是说这种找比自己体积大的盒子容量的关系是一对一的。
    简单来说就是某个盒子只能配对一个比自己大的,并且保证尽量每个盒子都能找到!
    这就是一个二分图最大匹配问题。和找男女朋友一样的。
    匈牙利算法,有机会就上,没有机会创造机会也要上!

    #include<stdio.h>///二分图最大匹配
    #include<string.h>
    int match[505];
    bool edge[505][505],vis[505];///edge存图,表示在i是否能装下j盒子,vis标记是否询问过某个点
    int n,k;
    bool KM(int x)///DFS求增广路(求每个盒子所能对应的匹配,能被谁装进去)
    {
        for(int i=1;i<=n;i++)///遍历能装下x编号的盒子
        {
            if(!vis[i]&&edge[x][i])
            {
                vis[i]=true;///标记访问点
                if(match[i]==0||KM(match[i]))
                {
                    match[i]=x;///更新配对关系
                    return true;
                }
            }
        }
        return false;///若遍历了所有点仍未找到盒子装下,这个盒子裸露在外
    }
    int main()
    {
        while(scanf("%d%d",&n,&k)!=EOF)
        {
            int x,y;
            memset(edge,false,sizeof(edge));
            memset(match,0,sizeof(match));
            for(int i=0;i<k;i++)
            {
                scanf("%d%d",&x,&y);
                edge[x][y]=true;///这里x盒子能被y盒子装下,不表示y盒子能被x盒子装下,也就是有向图
            }
            int sum=0;
            for(int i=1;i<=n;i++)
            {
                memset(vis,false,sizeof(vis));
                KM(i);
            }
            for(int i=1;i<=n;i++)if(match[i]==0)sum++;///最后计数没有被装下,没有配对的盒子个数
            printf("%d
    ",sum);
        }
    }
    

    match数组用于记录配对关系,也就是match[i]表示第i号盒子装了几号盒子。一开始大家都是空的用0表示,然后DFS为每个盒子配对,通过遍历能装下自己的盒子来搜索能和自己配对的盒子(不是能装下就一定配对了的)。对于每个盒子i,我们询问所有能装下自己的盒子,询问过的盒子做标记。表示这个盒子问过了,我已经为其找到了配对,而对于一个当前盒子中没有询问过的盒子,我将问他能不能装我,一种情况是,他谁都没装,那装我没问题!直接配对,第二种情况,他已经装了别的盒子,那么我让这个别的盒子再去寻找其他能装别的盒子的盒子,如果找到了,我将被我问的这个盒子装进去。
    这个vis询问标记是对于每个盒子而言的,也就是说我1号盒子问过了2号盒子,那么1将不再问2(废话),即使间接的也不能再问(间接是指在DFS过程中可能会让别的盒子再去问2),因为这样会无限递归。
    而对于盒子3,3没问过2,就可以询问。
    最后统计match中为0盒子个数,也就是没有装盒子的盒子,这就是最终没有被装的盒子的数量。(想想,层层包裹的盒子作为一个集合,这个盒子中只有一个没装盒子,也只有一个没被盒子装,没装盒子的盒子match为0,根据这个特点找到0的个数,即是集合的个数,也是裸露在外的盒子个数)

  • 相关阅读:
    Redis数据类型
    Linux配置Redis
    Linux配置ActiveMQ
    Linux配置Docker
    3、Spring Boot日志
    2、Spring Boot配置
    1. Spring Boot入门
    Linux(centos6.8)配置Redis
    okhttp禁止重定向
    123
  • 原文地址:https://www.cnblogs.com/kuronekonano/p/11794311.html
Copyright © 2011-2022 走看看