题目大意:

有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. Unsupported major.minor version 52.0 处理方式

    Exception in thread "main" java.lang.UnsupportedClassVersionError: com/globalroam/openstac ...

  2. 为什么要采用外部js文件

    这篇文章主要讲的是为什么要采用外部js文件,有什么好处. 为什么不把js内嵌在html中呢,这样不是好分析吗?对,这样你是好分析,同样的别人呢?不内嵌在html中有如下原因:   安全性: 只要查看页 ...

  3. php中利用HttpClient判断页面状态

    $url = ''; $info = parse_url($url); $httpClient = new HttpClient($info['host']); $httpClient->get ...

  4. 一个Restful Api的访问控制方法

    最近在做的两个项目,都需要使用Restful Api,接口的安全性和访问控制便成为一个问题,看了一下别家的API访问控制办法. 新浪的API访问控制使用的是AccessToken,有两种方式来使用该A ...

  5. iOS AVAudioPlayer 提示音

    NSString *urlPath = [[NSBundle mainBundle] pathForResource:@"" ofType:@""]; NSUR ...

  6. Java学习笔记--Swing用户界面组件

    很多与AWT类似. 事件处理参考:Java学习笔记--AWT事件处理 1.设计模式: 模型:存储内容视图:显示内容控制器:处理用户输入· 2. 文本输入常用组件 2.1 文本域: JLabel lab ...

  7. Android原理View、ViewGroup

    Android的UI界面都是由View和ViewGroup及其派生类组合而成的.其中,View是所有UI组件的基类,而ViewGroup是容纳这些组件的容器,其本身也是从View派生出来的.Andro ...

  8. bzoj 3238 Ahoi2013 差异

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2357  Solved: 1067[Submit][Status ...

  9. 感知机(perceptron)

    二类分类的线性分类模型,属于判别模型,利用梯度下降法对损失函数进行极小化求得感知机模型分为原始形式和对偶形式,是神经网络和支持向量机的基础 由输入控件到输出控件的如下函数: f(x)=sign(W.X ...

  10. hdu 3832 Earth Hour

    http://acm.hdu.edu.cn/showproblem.php?pid=3832 #include <cstdio> #include <iostream> #in ...