SPOJ 4206 Fast Maximum Matching (二分图最大匹配 Hopcroft-Carp 算法 模板)
题目大意:
有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 算法 模板)的更多相关文章
- 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 ...
- "《算法导论》之‘图’":不带权二分图最大匹配(匈牙利算法)
博文“二分图的最大匹配.完美匹配和匈牙利算法”对二分图相关的几个概念讲的特别形象,特别容易理解.本文介绍部分主要摘自此博文. 还有其他可参考博文: 趣写算法系列之--匈牙利算法 用于二分图匹配的匈牙利 ...
- 二分图最大匹配:匈牙利算法的python实现
二分图匹配是很常见的算法问题,一般用匈牙利算法解决二分图最大匹配问题,但是目前网上绝大多数都是C/C++实现版本,没有python版本,于是就用python实现了一下深度优先的匈牙利算法,本文使用的是 ...
- 51nod 2006 飞行员配对(二分图最大匹配) 裸匈牙利算法 求二分图最大匹配题
题目: 题目已经说了是最大二分匹配题, 查了一下最大二分匹配题有两种解法, 匈牙利算法和网络流. 看了一下觉得匈牙利算法更好理解, 然后我照着小红书模板打了一遍就过了. 匈牙利算法:先试着把没用过的左 ...
- 二分图最大匹配(匈牙利算法)简介& Example hdu 1150 Machine Schedule
二分图匹配(匈牙利算法) 1.一个二分图中的最大匹配数等于这个图中的最小点覆盖数 König定理是一个二分图中很重要的定理,它的意思是,一个二分图中的最大匹配数等于这个图中的最小点覆盖数.如果你还不知 ...
- 【模板】二分图最大匹配(匈牙利算法)/洛谷P3386
题目链接 https://www.luogu.com.cn/problem/P3386 题目大意 给定一个二分图,其左部点的个数为 \(n\),右部点的个数为 \(m\),边数为 \(e\),求其最大 ...
- 无权二分图最大匹配 HDU2063 匈牙利算法 || Hopcroft-Karp
参考两篇比较好的博客 http://www.renfei.org/blog/bipartite-matching.html http://blog.csdn.net/thundermrbird/art ...
- 【hihocoder 1122】二分图二•二分图最大匹配之匈牙利算法
[Link]:https://hihocoder.com/problemset/problem/1122 [Description] [Solution] 二分图匹配,匈牙利算法模板题; 这里我先把染 ...
- SPOJ 4110 Fast Maximum Flow (最大流模板)
题目大意: 无向图,求最大流. 算法讨论: Dinic可过.终于我的常数还是太大.以后要注意下了. #include <cstdio> #include <cstring> # ...
随机推荐
- Java图片工具类,完成图片的截取和任意缩放
package com.common.util; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Renderin ...
- K-D Tree题目泛做(CXJ第二轮)
题目1: BZOJ 2716 题目大意:给出N个二维平面上的点,M个操作,分为插入一个新点和询问到一个点最近点的Manhatan距离是多少. 算法讨论: K-D Tree 裸题,有插入操作. #inc ...
- Scala学习文档-列表的使用
注:列表是不可变的,不能通过赋值改变列表的元素 列表具有递归结构,数组是连续的 scala里的列表类型是协变的? --> scala中的逆变与协变 分治原则 //自定义实现:::操作符 def ...
- hex、bin、elf、axf文件区别
AXF和ELF axf文件是ARM的调试文件,除了包含bin的内容之外,还附加了其他的调试信息,这些调试信息加在可执行的二进制数据的前面.在调试的时候,这些调试信息是不必下到RAM中去的,真正下到RA ...
- DHTMLEdit
DHTMLEdit POP3研究了一会,发现如果要写一个类似FOXMAIL的东西,还需要解决一个编辑的问题.以为邮件是支持HTML编辑的. 网上查了一会发现可以使用WINDOWS自带的控件:DHT ...
- 【转】android cts failed items
原文网址:http://blog.csdn.net/linsa0517/article/details/19031479 Fail的一些修改 1.直接设置问题 estUnknownSourcesO ...
- Increasing/ Decreasing Stack
对于此类问题: 对于元素nums[i],找出往左/右走第一个比它小/大的数字 我们常常用递增栈/递减栈实现. 递增栈实现第一个比它小 递减栈实现第一个比它大 Example: 2 1 5 6 2 3 ...
- 再造轮子之网易彩票-第一季(IOS 篇 by sixleaves)
前言 在网上看了别人做的模仿网易彩票的项目, 于是也跟着用自己的想法做了一篇.写这篇博客的目的, 在于UI综合的一次小练习, 同时总结和串联其各个控件之间的应用.封装思想等.考虑到有人上不了githu ...
- poj2739
Sum of Consec ...
- hbase的thriftserver开启
说明:hbase的thriftserver默认已经编译好,可以使用,不需要跟hadoopthrift一样配置. 要使用Hbase的thrift接口,必须将它的服务启动,命令行为: hbase-deam ...