题目大意:

有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. JavaScript优化参考

    最近在为管理系统的网站做点优化,压缩都用了工具,就没太多可以讨论的. 主要还是代码上的精简和优化.稍微整理一下,顺便做点测试. 这里先贴上项目中用来替代iFrame的Ajax处理的局部代码,本人比较讨 ...

  2. VC:CString用法整理(转载)

    1.CString::IsEmpty BOOL IsEmpty( ) const; 返回值:如果CString 对象的长度为0,则返回非零值:否则返回0. 说明:此成员函数用来测试一个CString ...

  3. EL表达式复习

    EL表达式格式: 格式1:${objName.attribute} 执行的过程为:从pageContext.request.session.application中依次查找绑定名为“user”的对象, ...

  4. 浅析 JavaScript 组件编写

    之前因项目需要也编写过一些简单的JS组件,大多是基于JQuery库的,一直也没有过总结,导致再次写到的时候还去Google, 近日看到一个文章总结的挺好,拿过整理一下做个备忘. 此次同样是基于jque ...

  5. ubuntu12.04 安装 ruby1.9.3

    sudo apt-add-repository ppa:brightbox/ruby-ng sudo apt-get update sudo apt-get install ruby rubygems ...

  6. PHP Warning: phpinfo(): It is not safe to rely on the system's timezone setting

    错误描述: PHP Warning:  phpinfo(): It is not safe to rely on the system's timezone settings. You are *re ...

  7. 用RBG颜色设置自定义颜色

    这个是Mac自带的测色计   快捷键shift + command + c即可复制RBG格式的颜色 #DD0000 这个是csdn 的logo里的红色 我们得到的是十六位颜色代码 但是UIColor( ...

  8. keil c51中C程序的启动过程

    汇编是从org 0000h开始启动,那么keil c51是如何启动main()函数的?keil c51有一个启动程序startup.a51,它总是和c程序一起编译和链接.下面看看它和main()函数是 ...

  9. LCD的背光及觸摸屏

    液晶的发现可追溯到19 世纪末,1888 年被奥地利植物学家发现.它是一种在一定温度范围内呈现既不同于固态.液态,又不同于气态的特殊物质态.既具有晶体所具有的各向异性造成的双折射性,又具有液体所特有的 ...

  10. 时刻注意QT与Windows系统的不同(惨痛教训)

    其实就一条:WINAPI使用'\',而QT使用'/'.如果程序立刻崩溃的话,是很难看出端倪的,所以要时刻注意...