二分图的最大匹配——最大流EK算法
序:
既然是个图,并且求边数的最大值。那么这就可以转化为网络流的求最大流问题。
只需要将源点与其中一子集的所有节点相连,汇点与另一子集的所有节点相连,将所有弧的流量限制置为1,那么最大流 == 最大匹配。(感谢yulemao大神的指点)
只需要在初始化的时候修改一下,就可以直接用求最大流的算法模板了。
本文代码使用EK算法, 为POJ 1469的AC代码。
EK算法解析
源代码:
/*
About: 二分图最大匹配_网络流EK算法
2017/04/22
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <string.h>
using namespace std;
#define INF 0x3f3f3f
#define maxm 200005
#define maxn 10005
struct Edge{
int st, en, num;
Edge(){}
Edge(int s, int e, int n):
st(s), en(e), num(n){}
}flow[maxm];
int n, m;
int st = maxn-2, en = maxn-1;
int pre[maxn], re[maxn][maxn/10], num[maxn];
int q[maxn], curr_pos, st_pos, end_pos, ne, max_flow;
bool wh[maxn];
int cur;
int input;
char *X, *Buffer, c;
void Get_All()
{
long long file_lenth;
fseek(stdin, 0, SEEK_END);
file_lenth = ftell(stdin);
rewind(stdin);
Buffer = (char*)malloc(1*file_lenth);
fread(Buffer,1, file_lenth, stdin);
X = Buffer;
return ;
}
int Get_Int()
{
c = *X;
input = 0;
while(c < '0' || c > '9') c = *++X;
while(c >= '0' && c <= '9')
{
input = input*10+c-'0';
c = *++X;
}
return input;
}
void Add_Edge(int st, int en)
{
flow[cur] = Edge(st, en, 1);
flow[cur^1] = Edge(en, st, 0);
re[flow[cur].st][++num[flow[cur].st]] = cur;
re[flow[cur].en][++num[flow[cur].en]] = cur^1;
cur += 2;
return ;
}
void Init()
{
cur = 0;
memset(num, -1, sizeof num);
max_flow = 0;
}
static void Read()
{
int a, nums;
n = Get_Int(), m = Get_Int();
for(unsigned i = 0; i != n; ++i)
{
Add_Edge(st, i);
nums = Get_Int();
for(unsigned j = 0; j != nums; ++j)
{
a = Get_Int();
Add_Edge(i, a+n);
}
}
for(unsigned j = 1; j != m+1; ++j)
{
Add_Edge(j+n, en);
}
return ;
}
static bool Bfs(int st, int en)
{
int i, j;
st_pos = -1, end_pos = 0;
memset(wh, 0, sizeof wh);
wh[st] = 1;
q[0] = st;
while(st_pos != end_pos)
{
curr_pos = q[++st_pos];
for(i = 0; i < num[curr_pos]+1; ++i)
{
j = re[curr_pos][i];
if(flow[j].st == curr_pos && flow[j].num > 0 && !wh[flow[j].en])
{
ne = flow[j].en;
wh[ne] = 1;
pre[ne] = j;
q[++end_pos] = flow[j].en;
if(ne == en) return true;
}
}
}
return false;
}
void EK(int start_pos, int end_pos)
{
int i, minn;
while(Bfs(start_pos, end_pos))
{
minn = INF;
for(i = end_pos; i != st; i = flow[pre[i]].st)
{
minn = min(minn, flow[pre[i]].num);
}
for(i = end_pos; i != st; i = flow[pre[i]].st)
{
flow[pre[i]].num -= minn;
flow[pre[i]^1].num += minn;
}
max_flow += minn;
}
return ;
}
void Print()
{
if(max_flow == n)
{
cout << "YES" << endl;
}
else
{
cout << "NO" << endl;
}
return ;
}
int main()
{
freopen("test.in", "r", stdin);
Get_All();
int times = Get_Int();
while(times --> 0)
{
Init();
Read();
EK(st, en);
Print();
}
fclose(stdin);
return 0;
}
需要注意的是,在实测中,上一篇文章所使用的匈牙利算法耗时70+ms,但是本文代码耗时600+ms。
所以利用最大流算法计算二分图的最大匹配只是借鉴思路,若不是有特殊原因,建议不使用。
至此结束。
箜瑟_qi 2017.04.22 16:02
二分图的最大匹配——最大流EK算法的更多相关文章
- 最大流EK算法/DINIC算法学习
之前一直觉得很难,没学过网络流,毕竟是基础知识现在重新来看. 定义一下网络流问题,就是在一幅有向图中,每条边有两个属性,一个是cap表示容量,一个是flow 表示流过的流量.我们要求解的问题就是从S点 ...
- 最大流——EK算法
一.算法理论 [基本思想] 反复寻找源点s到汇点t之间的增广路径,若有,找出增广路径上每一段[容量-流量]的最小值delta,若无,则结束.在寻找增广路径时,可以用BFS来找,并且更新残留网络的值(涉 ...
- (通俗易懂小白入门)网络流最大流——EK算法
网络流 网络流是模仿水流解决生活中类似问题的一种方法策略,来看这么一个问题,有一个自来水厂S,它要向目标T提供水量,从S出发有不确定数量和方向的水管,它可能直接到达T或者经过更多的节点的中转,目前确定 ...
- vector实现最大流EK算法
序: 在之前的文章中实现了不利用STL实现EK算法,效率也较高.这次我们企图简化代码,减少变量的使用与手写模拟的代码. 注意:vector等STL的container在不开O2优化的时候实现同一个效果 ...
- 最大流EK算法模板
最近学了下最大流算法,大概思想算是懵懵懂懂了,现在想把模板记录下来,以备后面深刻学习之用. #include<cstdio> #include<cstring> using n ...
- POJ-1459(最大流+EK算法)
Power Network POJ-1459 这题值得思索的就是特殊的输入,如何输入一连串字符.这里采用的方法是根据输入已知的输入格式,事先预定好要接受的数据类型. 这里套用的板子也是最大流的模板,但 ...
- 【转】最大流EK算法
转自:http://www.cnblogs.com/kuangbin/archive/2011/07/26/2117636.html 图-1 如图-1所示,在这个运输网络中,源点S和汇点T分别是1,7 ...
- POJ1273 最大流 EK算法
套了个EK的模板 //#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include <stdi ...
- 最大流EK算法
给定一个有向图G=(V,E),把图中的边看作 管道,每条边上有一个权值,表示该管道 的流量上限.给定源点s和汇点t,现在假设 在s处有一个水源,t处有一个蓄水池,问从 s到t的最大水流量是多少? 网络 ...
随机推荐
- [SQL] SQL 基础知识梳理(七)- 集合运算
SQL 基础知识梳理(七)- 集合运算 目录 表的加减法 联结(以列为单位) 一.表的加减法 1.集合:记录的集合(表.视图和查询的执行结果). 2.UNION(并集):表的加法 -- DDL:创建表 ...
- C++数据
const :常量 ~x == -++x == -(x+1) 二进制数,1变为0,0变为1 ^ 相同为0,不同为1 & ...
- ICC_lab总结——ICC_lab3:布局
PS:字丑,禁止转载. 做到了ICC workshop的第三个实验,理论与实践相结合,于是,先放一张总结图,这张总结图来自前面的博客,放在这里用来体现理论和实践的联系: 这个就是布局的理论部分,在IC ...
- struts2(四) ognl表达式、值栈、actionContext之间的关系
今天来说说ognl表达式在struts2中的运用. --wh 一.什么是Ognl? 通过百度百科查询到的解释,其中详细的说明了OGNL的作用. 下面我们就对OGNL这5个作用进行讲解 1.存取对象的任 ...
- bing翻译API调用方法
概述 前一段时间,遇到一个需求,需要对文章进行翻译,由于客户公司员工有国内的人员,也有国外的人员,为了照顾国外的同事,客户提出,当用户在手机端发布帖子,需要同时把帖子的内容翻译成英文,方便用户阅读.于 ...
- Hadoop2.7.3+Spark2.1.0完全分布式集群搭建过程
1.选取三台服务器(CentOS系统64位) 114.55.246.88 主节点 114.55.246.77 从节点 114.55.246.93 从节点 之后的操作如果是用普通用户操作的话也必须知道r ...
- web浏览器上传超大文件插件
如今基于浏览器安装插件的时代已经过时,让人觉得比较low,基于非插件的文件上传大都有限制,给大家推荐一款插件,基于大文件切割原理上传的插件,解决大家的难题! 项目链接http://www.twinkl ...
- 【Spring】BeanFactory解析bean详解
在该文中来讲讲Spring框架中BeanFactory解析bean的过程,该文之前在小编原文中有发表过,要看原文的可以直接点击原文查看,先来看一个在Spring中一个基本的bean定义与使用. pac ...
- robotium问答
robotium问答 robotium集成instrumentation robotium如何定位控件? search类获取当前所有的view,然后根据类型或者文本去筛选,找到view后获取坐标, ...
- 基于 Spring MVC 的开源测试用例管理系统以及开发自测的实践
早前公司领导提出让开发自测,测试么也做做开发.当然了,为了保证自测质量,测试用例仍需测试提供,所以为了提高开发自测的效率和质量,我们开发了捉虫记.捉虫记是一个完整的Spring MVC项目,现已开源, ...