[二分图初步]【模板】二分图匹配

题目链接

题目简述:就是二分图板子。

Q:什么是二分图呢?

A:二分图就是一个无向图可以分成两个子集,且满足这个图中每条边的端点都是属于不同子集的。

什么意思呢?上面这个看起来好像有点晦涩难懂,其实这个可以很好地用生活来解释。在现实生活中,每个班级都有那么几对“关系异常”的男女。我们将整个年级中所有这样的人拉出来站在一起,如果发现没有一对是同性的(笑),那么就说明这是一群符合大众道德观(我不歧视同性恋)的早恋学生,那么可以说这群人是符合二分图的定义的。这相当于所有人是一个图,他们之间的情愫就是将他们相连的边,不同的性别为不同的子集,两个子集不相交(双性人太草),且每条边连接着的端点不在同一个子集(如果在的话就有同性恋啦)。

了解了二分图的定义之后,那么二分图会发生那些有趣的事情呢?我们还是依靠上面的模型。首先定义一个词:匹配,也可以称作某条边和它连着的两个点的合称。在这个模型中就相当于是一对情侣的意思。一个图里可以有很多个匹配,就跟一个年级里可能有很多对情侣是一样的(不要早恋!),那么一个图中的匹配满足互不相交的性质,匹配的数量最多的情况叫做最大匹配。这个解释起来也很简单,在把情侣们拉出来后,我们会发现有些渣男/女,与他们相恋的可能有两个或者多个(太草了),这时候大家醋意勃发,要求这些人立刻做出决定终生的选择,也就是相互确立关系,成为匹配。匹配不相交也就是因为都决定终生了就不允许存在三角关系了。

那么为了使这些学生能够得到幸福(早恋是得不到幸福的!),我们就要找到最大子集。那怎么办呢?我们这个时候需要用到一个算法-匈牙利算法。

我们引进一个定义:增广路。但是由于很复杂(有兴趣的自己查),我就直接作出感性的解释。首先我们有着一些标记:与某人确定关系的,以及某人是否正在调换过程中。以下的解释均由男孩子来选女孩子(反过来也是一样的),首先,对于一个男生,他要开始选了,他就找啊找,那么遇到的有两种情况:1.找的女生已经有选择了 2.还没选择。1的话我们要为自己的幸福争取一些机会,于是尝试着请求以下让别人换一个男朋友,那么此时就问男同胞,你能不能再找一个?(此时这个女生已经在调换过程中了,所以男同胞不能再找她),如果能换(函数返回值为一),那么争取到了这一个幸福(横刀夺爱太草),然后你我关系确认一下(户口簿改名字?),再返回1(因为有可能是别人让我换一个,要给别人一个答复),换不了就只有找其他人了。2就直接选就好了(毕竟还能再换)。

那么算法部分已经结束了,要注意一个点:当这个函数不是被自己调用而是主函数调用的时(也就是不是别人让我换,而是我自己要找),一定要清零标记数组!(即是否在调换过程的标记),并且这个标记只标记被选择的哪一方就行了。(要问为什么的话就是这个数组的作用就在于不让男孩子找迷糊了,给他指出哪些是碰不得的,因为别人正等着换)

代码

#include<iostream>
#include<cstdio>
#include<fstream>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
int read(){
    char ch;
    int res=0,f=1;
    ch=getchar();
    while(ch<‘0‘||ch>‘9‘){
        if(ch==‘-‘)f=-1;
        ch=getchar();
    }
    while(ch>=‘0‘&&ch<=‘9‘){
        res=res*10+(ch-‘0‘);
        ch=getchar();
    }
    return res*f;
}
const int MAXN=20005;
int n,m,e,u,v,ans;
bool is_to[MAXN][MAXN],vis[MAXN];
int l[MAXN],r[MAXN];
bool dfs(int x){
    for(int i=1;i<=m;++i){
        if(!vis[i]&&is_to[x][i]){
            vis[i]=1;
            if(!r[i]||dfs(r[i])){
                r[i]=x;
                l[x]=i;
                return 1;
            }
        }
    }
    return 0;
}
int main(){
    n=read();m=read();e=read();
    for(int i=1;i<=e;++i){
        u=read();v=read();
        if(u<=n&&v<=m)is_to[u][v]=1;
    }
    for(int i=1;i<=n;++i)if(!l[i]){
        memset(vis,0,sizeof(vis));
        ans+=dfs(i);
    }
    cout<<ans;
    return 0;
}

匈牙利算法就是DFS的部分啦。

原文地址:https://www.cnblogs.com/clockwhite/p/11564465.html

时间: 2024-10-16 17:33:35

[二分图初步]【模板】二分图匹配的相关文章

【二分图最大权完美匹配】【KM算法模板】【转】

[文章详解出处]https://www.cnblogs.com/wenruo/p/5264235.html KM算法是用来求二分图最大权完美匹配的.[也就算之前的匈牙利算法求二分最大匹配的变种??] 这里就贴一下模板代码..2333... 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 using namespace std; 6

二分图最大权值匹配 KM算法 模板

大佬讲的太好了!!!太好了!!! http://www.cnblogs.com/wenruo/p/5264235.html KM算法用来求二分图最大权完美匹配. 本文配合该博文服用更佳:趣写算法系列之--匈牙利算法 本文没有给出KM算法的原理,只是模拟了一遍算法的过程.另,博主水平较差,发现问题欢迎指出,谢谢!!!! 现在有N男N女,有些男生和女生之间互相有好感,我们将其好感程度定义为好感度,我们希望把他们两两配对,并且最后希望好感度和最大. 怎么选择最优的配对方法呢? 首先,每个女生会有一个期

POJ--2289--Jamie&amp;#39;s Contact Groups【二分图的多个匹配+二分法答案】

链接:id=2289">http://poj.org/problem?id=2289 意甲冠军:有n个人,m个分组,每一个人能够分配到一些组别.问怎样分能使得人数最多的组别人数最少. 思路:这道题二分+网络流也能够做,我这里是二分图多重匹配的做法.由于一个组别是一对多的关系,所以是多重匹配.我们二分多重匹配的限制,得到最小的限制可使二分图匹配,这个限制就是答案. 网上找的模板 #include<cstring> #include<string> #include&l

二分图【模板】

二分图:原图G的顶点可以分类两个集合X和Y,所有的边关联的两个顶点恰好一个属于集合X,另一个属于集合Y,则称该图为二分图. 二分图匹配:给定一个二分图G,在G的一个子图M中,M的边集中的任意两条边都不依附于同一个顶点,即一个顶点最多只有一条边.则称M是一个匹配. 二分图最大匹配:图中包含边数最多的匹配称为图的最大匹配. 二分图完美匹配:如果所有点都在匹配边上,则称这个最大匹配是完美匹配. 二分图多重匹配:二分图匹配一对一匹配,这里允许集合Y中的一个元素和集合X中的多个元素匹配(一般有最大限制N)

求二分图最大权一个匹配(未必最大匹配),/费用流

题意:依据题意建立模型:给一幅混合图,有些带边.求选取一些边,使得权值最大,并且保证每一个点入度和出度都最多是1. 開始的时候题意理解出错. 思路:件二分图.最大权匹配,可是能够不是全部点都參与匹配,(都參与未必最大.因此,在费用流法基础上:每一个X部点向汇点也有边就可以. 这样保证最大流为n,并且未必全部点都匹配. #include<cstdio> #include<iostream> #include<queue> #include<cstring> #

HiHo1121 : 二分图一?二分图判定(模板题)

描述 大家好,我是小Hi和小Ho的小伙伴Nettle,从这个星期开始由我来完成我们的Weekly. 新年回家,又到了一年一度大龄剩男剩女的相亲时间.Nettle去姑姑家玩的时候看到了一张姑姑写的相亲情况表,上面都是姑姑介绍相亲的剩男剩女们.每行有2个名字,表示这两个人有一场相亲.由于姑姑年龄比较大了记性不是太好,加上相亲的人很多,所以姑姑一时也想不起来其中有些人的性别.因此她拜托我检查一下相亲表里面有没有错误的记录,即是否把两个同性安排了相亲. OK,让我们愉快的暴力搜索吧! 才怪咧. 对于拿到

HDU 2444 The Accomodation of Students (二分图判定,二分图匹配,匈牙利算法)

题意:有一堆的学生关系,要将他们先分成两个组,同组的人都不互不认识,如果不能分2组,输出No.若能,则继续.在两组中挑两个认识的人(每组各1人)到一个双人房.输出需要多少个双人房? 思路: 先判定是否为二分图,可以用黑白着色法(DFS或BFS都行).若是二分图,再进行匹配,用匈牙利算法,注:给的是整个图,没有区分男女,用邻接表比较好. 1 #include <bits/stdc++.h> 2 #define LL long long 3 using namespace std; 4 const

UVa 1349 (二分图最小权完美匹配) Optimal Bus Route Design

题意: 给出一个有向带权图,找到若干个圈,使得每个点恰好属于一个圈.而且这些圈所有边的权值之和最小. 分析: 每个点恰好属于一个有向圈 就等价于 每个点都有唯一后继. 所以把每个点i拆成两个点,Xi 和 Yi ,然后求二分图最小权完美匹配(流量为n也就是满载时,就是完美匹配). 1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 const int maxn = 200 + 10; 6 const int INF = 10000000

带权二分图的最大权匹配 KM算法模版

带权二分图的最大权匹配 KM算法模版 下面是kuangbin大神的模版,已通过西电oj1048的测试 #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<vector> #include<stack> #include<queue> #include<set

HDU2255-奔小康赚大钱-二分图最大权值匹配-KM算法

二分图最大权值匹配问题.用KM算法. 最小权值的时候把权值设置成相反数 1 /*--------------------------------------------------------------------------------------*/ 2 3 #include <algorithm> 4 #include <iostream> 5 #include <cstring> 6 #include <ctype.h> 7 #include &l