立志成为饮水机!

二分图 学习记 之 匈牙利算法

二分图匹配学习记

这个博客目前还没更完

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

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

 

posted @ 2019-06-28 21:07  寒冰大大  阅读(324)  评论(1编辑  收藏  举报