• Luogu 1894 [USACO4.2]完美的牛栏The Perfect Stall / POJ 1274 The Perfect Stall(二分图最大匹配)


    Luogu 1894 [USACO4.2]完美的牛栏The Perfect Stall / POJ 1274 The Perfect Stall(二分图最大匹配)

    Description

    农夫约翰上个星期刚刚建好了他的新牛棚,他使用了最新的挤奶技术。不幸的是,由于工程问题,每个牛栏都不一样。第一个星期,农夫约翰随便地让奶牛们进入牛栏,但是问题很快地显露出来:每头奶牛都只愿意在她们喜欢的那些牛栏中产奶。上个星期,农夫约翰刚刚收集到了奶牛们的爱好的信息(每头奶牛喜欢在哪些牛栏产奶)。一个牛栏只能容纳一头奶牛,当然,一头奶牛只能在一个牛栏中产奶。

    给出奶牛们的爱好的信息,计算最大分配方案。

    Input

    第一行 两个整数,N (0 <= N <= 200) 和 M (0 <= M <= 200) 。N 是农夫约翰的奶牛数量,M 是新牛棚的牛栏数量。

    第二行到第N+1行 一共 N 行,每行对应一只奶牛。第一个数字 (Si) 是这头奶牛愿意在其中产奶的牛栏的数目 (0 <= Si <= M)。后面的 Si 个数表示这些牛栏的编号。牛栏的编号限定在区间 (1..M) 中,在同一行,一个牛栏不会被列出两次。

    Output

    只有一行。输出一个整数,表示最多能分配到的牛栏的数量.

    Sample Input

    5 5
    2 2 5
    3 2 3 4
    2 1 5
    3 1 2 5
    1 2

    Sample Output

    4

    Http

    Luogu:https://www.luogu.org/problem/show?pid=1894
    POJ:https://vjudge.net/problem/POJ-1274

    Source

    二分图最大匹配

    解决思路

    这是一道二分图最大匹配的模板题。

    对于一只牛和其喜欢的牛棚,我们连一条有向边。我们定义对于牛棚u,Match[u]为其匹配的牛的编号。

    我们依次枚举每一只牛u来修改匹配。当找到一个可以匹配的空牛棚时,我们就直接将该空牛棚的Match值置为该牛u。若该牛棚已经被匹配,那么我们向下dfs该牛棚之前对应的那只牛v,看看能否让其更改匹配,对于牛v的操作与牛u类似,但要注意不要dfs重复的牛。重复上述过程直到为牛u腾出位置,则把该牛棚的Match置为牛u,或不存在解则返回0。更多细节请参看代码。

    注意,POJ有多组数据

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    
    const int maxN=300;
    const int inf=2147483647;
    
    int n,m;
    vector<int> E[maxN];//存边
    bool vis[maxN];//牛棚是否已经访问过,避免重复
    int Match[maxN];//存下牛棚匹配的牛的编号,-1表示还未匹配
    
    bool dfs(int u);
    
    int main()
    {
        while(cin>>n>>m)
        {
    for (int i=1;i<=n;i++)
    E[i].clear();
        for (int i=1;i<=n;i++)
        {
            int S;
            cin>>S;
            for (int j=1;j<=S;j++)
            {
                int x;
                cin>>x;
                E[i].push_back(x);//连边
            }
        }
    
        memset(Match,-1,sizeof(Match));
        int cnt=0;
        for (int i=1;i<=n;i++)
        {
            memset(vis,0,sizeof(vis));//每一次进行匹配之前都要清空
            if (dfs(i))//若成功匹配,则最大匹配数+1,因为多有一个点能够匹配
                cnt++;
        }
        cout<<cnt<<endl;
        }
        return 0;
    }
    
    bool dfs(int u)//1表示匹配成功,0表示不成功
    {
        for (int i=0;i<E[u].size();i++)
        {
            int v=E[u][i];
            if (vis[v]==0)
            {
                vis[v]=1;
                if ((Match[v]==-1) || dfs(Match[v]))//若当前牛棚可以匹配,或是dfs返回1(说明在dfs中成功匹配了),则此时要将新的值更新进去,同时向上一级dfs传值1
                {
                    Match[v]=u;
                    return 1;
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Nginx下载服务器配置文件
    php7连接mysql测试代码
    Vagrant 构建 Linux 开发环境
    清理buffer/cache/swap的方法梳理
    【12】
    python全栈目录
    Chrome启动后打开第一个网页很慢的解决方案
    Pycharm快捷键
    TEst
    1、Linux命令随笔
  • 原文地址:https://www.cnblogs.com/SYCstudio/p/7138221.html
Copyright © 2020-2023  润新知