题目大意:

有n1头公牛和n2头母牛,给出公母之间的m对配对关系,求最大匹配数。数据范围:  1 <= n1, n2 <= 50000, m <= 150000

算法讨论:

第一反应KM直接上,第二反应,KM是O(N^2 * M)的,会T成狗。

第二反应,看看大家是怎么做的。后来发现了一个名字叫 Hopcroft-Carp的二分图最大匹配的算法。可以在O(sqrt(n) * m)的时间内解决二分图的最大匹配问题。非常适合大数据的二分图匹配。所以就学习了一下。 我们知道,普通的匈牙利慢的原因是因为他一次深搜只找一条增广路,而HC算法是利用Bfs同时找多条增广路。

下面有网友提供的HC算法的原理:

SRbGa很早就介绍过这个算法,它可以做到O(sqrt(n)*e)的时间复杂度,并且在实际使用中效果不错而且算法本身并不复杂。

Hopcroft-Karp算法是Hopcroft和Karp在1972年提出的,该算法的主要思想是在每次增广的时候不是找一条增广路而是同时找几条不相交的最短增广路,形成极大增广路集,随后可以沿着这几条增广路同时进行增广。

可以证明在寻找增广路集的每一个阶段所寻找到的最短增广路都具有相等的长度,并且随着算法的进行最短增广路的长度是越来越长的,更进一步的分析可以证明最多只需要增广ceil(sqrt(n))次就可以得到最大匹配(证明在这里略去)。

因此现在的主要难度就是在O(e)的时间复杂度内找到极大最短增广路集,思路并不复杂,首先从所有X的未盖点进行BFS,BFS之后对每个X节点和Y节点 维护距离标号,如果Y节点是未盖点那么就找到了一条最短增广路,BFS完之后就找到了最短增广路集,随后可以直接用DFS对所有允许弧 (dist[y]=dist[x]+1,可以参见高流推进HLPP的实现)进行类似于匈牙利中寻找增广路的操作,这样就可以做到O(m)的复杂度。

实现起来也并不复杂,对于两边各50000个点,200000条边的二分图最大匹配可以在1s内出解~~

那么此题就可以用HC算法轻松跑过。提醒,一定要注意常数。SPOJ跑得太慢了。

果然我的常数是很大。。。。。。

Codes:

 #include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std; struct Hopcroft_Carp{
static const int N = + ;
static const int M = + ;
static const int oo = 0x3f3f3f3f; int n1, n2, res, tot;
int dsx[N], dsy[N], mx[N], my[N];
int que[N<<];bool vi[N<<];
int first[N<<], next[M];
int u[M], v[M]; void Clear(){tot = ; res = ;}
void Add(int from, int to){
++ tot;
u[tot] = from; v[tot] = to;
next[tot] = first[u[tot]];
first[u[tot]] = tot;
} bool bfs(){
for(int i = ; i <= n1; ++ i) dsx[i] = -;
for(int i = ; i <= n2; ++ i) dsy[i] = -;
res = oo; int head, tail;
head = tail = ;
for(int i = ; i <= n1; ++ i)
if(mx[i] == -) que[++ tail] = i, dsx[i] = ;
while(head <= tail){
int x = que[head];
if(dsx[x] > res) break; for(int i = first[x]; i; i = next[i]){
if(dsy[v[i]] == -){
dsy[v[i]] = dsx[x] + ;
if(my[v[i]] == -) res = dsy[v[i]];
else{
dsx[my[v[i]]] = dsy[v[i]] + ;
que[++ tail] = my[v[i]];
}
}
}
++ head;
}
return res != oo;
} bool dfs(int x){
for(int i = first[x]; i; i = next[i]){
if(!vi[v[i]] && dsy[v[i]] == dsx[x] + ){
vi[v[i]] = true;
if(my[v[i]] != - && dsy[v[i]] == res) continue;
if(my[v[i]] == - || dfs(my[v[i]])){
my[v[i]] = x;
mx[x] = v[i];
return true;
}
}
}
return false;
} int MaxMatch(){
int ans = ;
for(int i = ; i <= n1; ++ i) mx[i] = -;
for(int i = ; i <= n2; ++ i) my[i] = -; while(bfs()){
for(int i = ; i <= n1+n2; ++ i) vi[i] = false;
for(int i = ; i <= n1; ++ i)
if(mx[i] == - && dfs(i)) ans ++;
}
return ans;
}
}Two; int n1, n2, m; int main(){
int x, y;
scanf("%d%d%d", &n1, &n2, &m);
Two.Clear();
Two.n1 = n1; Two.n2 = n2;
for(int i = ; i <= m; ++ i){
scanf("%d%d", &x, &y);
Two.Add(x, y);
}
printf("%d\n", Two.MaxMatch());
return ;
}

SPOJ 4206

SPOJ 4206 Fast Maximum Matching (二分图最大匹配 Hopcroft-Carp 算法 模板)的更多相关文章

  1. hdu2389二分图之Hopcroft Karp算法

    You're giving a party in the garden of your villa by the sea. The party is a huge success, and every ...

  2. "《算法导论》之‘图’":不带权二分图最大匹配(匈牙利算法)

    博文“二分图的最大匹配.完美匹配和匈牙利算法”对二分图相关的几个概念讲的特别形象,特别容易理解.本文介绍部分主要摘自此博文. 还有其他可参考博文: 趣写算法系列之--匈牙利算法 用于二分图匹配的匈牙利 ...

  3. 二分图最大匹配:匈牙利算法的python实现

    二分图匹配是很常见的算法问题,一般用匈牙利算法解决二分图最大匹配问题,但是目前网上绝大多数都是C/C++实现版本,没有python版本,于是就用python实现了一下深度优先的匈牙利算法,本文使用的是 ...

  4. 51nod 2006 飞行员配对(二分图最大匹配) 裸匈牙利算法 求二分图最大匹配题

    题目: 题目已经说了是最大二分匹配题, 查了一下最大二分匹配题有两种解法, 匈牙利算法和网络流. 看了一下觉得匈牙利算法更好理解, 然后我照着小红书模板打了一遍就过了. 匈牙利算法:先试着把没用过的左 ...

  5. 二分图最大匹配(匈牙利算法)简介& Example hdu 1150 Machine Schedule

    二分图匹配(匈牙利算法) 1.一个二分图中的最大匹配数等于这个图中的最小点覆盖数 König定理是一个二分图中很重要的定理,它的意思是,一个二分图中的最大匹配数等于这个图中的最小点覆盖数.如果你还不知 ...

  6. 【模板】二分图最大匹配(匈牙利算法)/洛谷P3386

    题目链接 https://www.luogu.com.cn/problem/P3386 题目大意 给定一个二分图,其左部点的个数为 \(n\),右部点的个数为 \(m\),边数为 \(e\),求其最大 ...

  7. 无权二分图最大匹配 HDU2063 匈牙利算法 || Hopcroft-Karp

    参考两篇比较好的博客 http://www.renfei.org/blog/bipartite-matching.html http://blog.csdn.net/thundermrbird/art ...

  8. 【hihocoder 1122】二分图二•二分图最大匹配之匈牙利算法

    [Link]:https://hihocoder.com/problemset/problem/1122 [Description] [Solution] 二分图匹配,匈牙利算法模板题; 这里我先把染 ...

  9. SPOJ 4110 Fast Maximum Flow (最大流模板)

    题目大意: 无向图,求最大流. 算法讨论: Dinic可过.终于我的常数还是太大.以后要注意下了. #include <cstdio> #include <cstring> # ...

随机推荐

  1. C#如何设置下拉COMMBOX为不可输入,只有下拉条目

    设置下拉框的DropDownStyle属性为DropDownList

  2. 奇怪的JS正则表达式问题

    同一个正则表达式,为什么在JS里,用 var reg = new RegExp("..."); 定义,验证就各种失败,用 var reg=/.../; 定义,验证就对了...

  3. Trucking(HDU 2962 最短路+二分搜索)

    Trucking Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  4. a标签href不跳转 禁止跳转

    a标签href不跳转 禁止跳转 当页面中a标签不需要任何跳转时,从原理上来讲,可分如下两种方法: 标签属性href,使其指向空或不返回任何内容.如: <a href="javascri ...

  5. js 实现音乐播放

    <html><head><title>这种方式支持任何浏览器</title></head><body><div id=&q ...

  6. c++第三天

    今天完成的事情: [主线] 1.复习了一下昨天的内容 while(std::cin >> value) 扫描[标准输入] 2.在网上下载Sales_item.h 代码如下 #ifndef ...

  7. hdu 1599 find the mincost route

    http://acm.hdu.edu.cn/showproblem.php?pid=1599 floyd找最小环. #include <cstdio> #include <cstri ...

  8. vs 自动生成core dump文件

    一直以来觉着core dump这个东西很神奇,在初步学习的时候也没有个大方向,最近项目需要记录程序崩溃时的日志信息,因此在网上寻找相关的信息,此时core dump也成为了我重点关注的东西. 说说我的 ...

  9. cmake编译(编译目标)x86或x64

    if(CMAKE_CL_64)    #CMAKE的内建变量,如果是true,就说明编译器的64位的,自然可以编译64bit的程序 set(ADDRESS_MODEL 64) set(NODE_TAR ...

  10. android官方侧滑菜单DrawerLayout详解

    drawerLayout是Support Library包中实现了侧滑菜单效果的控件,可以说drawerLayout是因为第三方控件如MenuDrawer等的出现之后,google借鉴而出现的产物.d ...