题目大意:

有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++11 auto

    auto 关键字指示编译器使用已声明变量的初始化表达式或 lambda 表达式参数来推导其类型. 在大多情况下,建议您使用 auto 关键字(除非您确实需要转换),因为此关键字可提供以下好处: 可靠性 ...

  2. 最短路径floy算法———模板

    #include<cstdio>int n,i[1000][1000];int main(){ scanf("%d",&n); for (int a=1;a&l ...

  3. Keil C减小代码编译量大小的方法(gai)

    keil-C减小代码编译大小的方法整理 方法一:(通过优化代码减小) 1.1少做乘除运算,使用左/右移位来实现乘除 Eg ,普通:a = 0x80*4: 优化:a = 0x80<<2: 1 ...

  4. FCKeditor插件开发实例:uploadify多文件上传插件

    FCKeditor是一个专门使用在网页上属于开放源代码的所见即所得文字编辑器.它志于轻量化,不需要太复杂的安装步骤即可使用.它可和PHP.JavaScript.ASP.ASP.NET.ColdFusi ...

  5. Android再学习-20141018-布局-进度条

    20141018-Android再学习 对齐至控件的基准线 为了保证印刷字母的整齐而划定的线(四线三格的第三条线). android:layout_alignBaseline 与父控件的四个边缘对齐( ...

  6. 10步教你来优化WordPress速度 为服务器和访客减压

    1.Cookie的静态化制作 约有80%至90%的时间,访客要花费大量的时间等你的WordPress加载静态内容.这意味着,有大部分的时间,用户浏览您的网站,他们正在等待加载,如:图像,CSS,JS脚 ...

  7. 关于sublime3的配置笔记

    1.安装的插件有Anaconda, GitGutter, SublimeCodeIntel Anaconda会有长度超过80警报的问题, 影响写代码的时候的判断, 所以将Preferences/Pac ...

  8. Modified Kaprekar Numbers

    Link: https://www.hackerrank.com/challenges/kaprekar-numbers from __future__ import print_function d ...

  9. 根据样式获取被选中的checkbox

    <ul id="> </div> </li></ul> $("#btn_CheckManagerCompletionCreateAt ...

  10. 配色问题lingo实现

    大家好,我是小鸭酱,博客地址为:http://www.cnblogs.com/xiaoyajiang !调配颜色 要依次调配红.兰.白.黑.黄五种颜色 红  兰  白  黑  黄 红  0  6  1 ...