zoukankan      html  css  js  c++  java
  • 二分图 学习记 之 匈牙利算法

    二分图匹配学习记

    这个博客目前还没更完

    刚开始打的时候被毒瘤死了。。

    Leve1 洛谷 P3386 【模板】二分图匹配 

    匈牙利算法[Hungury算法]

    题目大意:给定一个二分图,结点个数分别为n,m,边数为e,求二分图最大匹配数

    一级代码

    1 进入dfs后,判断是否存在已经访问的情况
    2 然后枚举每一条与之相邻的边
    3 然后得到另一个点,这样做下去,判断是否存在一个未被访问或者一个可以改变自己的匹配的点
    4 接着dfs回溯,显然这个点也能够匹配了
    5 然后return即可 

    这里说一下第三步的意思

    例如这张图,这个过程就像找媳妇

    开始找到一个没有被访问的点

    好的,现在我们左边第一个点找到媳妇了

    然后第一个点完成,扫描第左边二个点,当第左边二个点愤怒地发现左边第一个点抢了他唯一能抢到的媳妇,这不得行啊,交涉交涉。

    于是按照蓝点的路径左边第一个点发动干涉后,第一个点说,好吧,反正我媳妇挺多的

    守国外武装干涉势力影响……

    幸福且美满的结局……

     那么现在代码就显而易见的简洁

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<stack>
    #include<vector>
    
    using namespace std;
    
    int head[10086],size,n,m,ee,have_meizi[10086],tot,vis[100860];
    
    struct edge{
        int next,to;
    }e[1008600];
    
    void addedge(int next,int to)
    {
        e[++size].next=head[next];
        e[size].to=to;
        head[next]=size;
    }
    
    int ycl(int a)
    {
        return a+n;
    }
    
    int hungary(int s)
    {
        int i,j;
        for(i=head[s];i;i=e[i].next)
        {
            j=e[i].to;
            if(vis[j]) continue;
            vis[j]=1;
            if(!have_meizi[have_meizi[j]]) 
            {
                have_meizi[j]=s;
                return 1;
            }
            else
            {
                if(hungary(have_meizi[j]))
                {
                    have_meizi[j]=s;
                    return 1;
                }
            }
        }
        return 0;
    }
    
    int main()
    {
        int i,j;
        scanf("%d %d %d",&n,&m,&ee);
        for(i=1;i<=ee;i++)
        {
            int t1,t2;
            scanf("%d %d",&t1,&t2);
            if(t1>n||t2>m||t1>m||t2>n) continue; 
            //t2=ycl(t2);
            addedge(t1,t2);
        }
        for(i=1;i<=m;i++)
        {
            memset(vis,0,sizeof(vis));
            if(hungary(i)) tot++; 
        }
        printf("%d",tot);
        return 0;
    }

    显然,这道题裸的的hack数据是精心构造的,然后这也会是新手的一个误区(比如我),

    hack数据:

    input
    5 5 11
    1 2
    1 5
    2 2
    2 3
    2 4
    3 1
    3 5
    4 1
    4 2
    4 5
    5 2
    output 
    4
  • 相关阅读:
    L2-004. 这是二叉搜索树吗?*
    L2-001. 紧急救援(最短路的变形)*
    L2-002. 链表去重(数组模拟)
    L1-028. 判断素数
    Linux相关
    2016ICPC-大连 A Simple Math Problem (数学)
    2016ICPC-大连 Convex (几何)
    2016ICPC-大连 To begin or not to begin (简单思维)
    TC704div2 C ModEquationEasy 矩阵快速幂+dp
    poj 3150 Cellular Automaton 矩阵快速幂
  • 原文地址:https://www.cnblogs.com/zsx6/p/11104792.html
Copyright © 2011-2022 走看看