网络(最大)流初步+二分图初步 (浅谈EK,Dinic, Hungarian method:]
本文中 N为点数,M为边数;
EK: (brute_force) ;
每次bfs暴力找到一条增广路,更新流量,代码如下 :
时间复杂度:O(NM²);
#include<bits/stdc++.h>
using namespace std; struct node{
int next,to,len;
}edge[]; int val[],head[],vis[],from[];
int n,m,s,t,ans,inf=,cnt=; inline void add_edge(int u,int v,int len){
edge[++cnt].to=v;
edge[cnt].next=head[u];
edge[cnt].len=len;
head[u]=cnt;
} inline bool bfs(){
queue <int> q;
memset(vis,,sizeof(vis));
val[s]=inf;
q.push(s);vis[s]=;
while(q.size()){
int u=q.front(); q.pop();
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(vis[v]||!edge[i].len)continue;
vis[v]=; q.push(v);
from[v]=i;
val[v]=min(val[u],edge[i].len);
if(v==t)return true;
}
}
return false;
} inline void update(){
int u=t;
while(u!=s){
int p=from[u];
edge[p].len-=val[t];
edge[p^].len+=val[t];
u=edge[p^].to;
}
ans+=val[t];
} int main(){
int x,y,z;
scanf("%d %d %d %d",&n,&m,&s,&t);
for(int i=;i<=m;i++){
scanf("%d %d %d",&x,&y,&z);
add_edge(x,y,z);
add_edge(y,x,);
}
while(bfs())update();
printf("%d\n",ans);
return ;
}
Dinic: 显然,EK算法每次只bfs找到一条增广路径是非常睿智低效的,Dinic算法就是通过dfs 每次找到一张增广网,从而使增广速度加快;
p.s. 当前弧优化:在dfs进行增广时,有些边已经对此次的增广做出了全部的贡献(换言之,他在当前的残量网络中已经没有贡献了),所以就不必再考虑它;
代码如下:
时间复杂度:O(Dinic(N, M)) O(N*M½) ~ O(M*N²);
//15owzLy1
//Dinic.cpp
//2018 10 10 11:51:55
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <vector>
#include <map>
#include <set>
#define lson tl, mid, rt<<1
#define rson mid+1, tr, rt<<1|1
#define pb(__) push_back(__)
#define fr() front()
#define bg() begin()
#define it iterator
#define INF 2100000000
typedef long long ll;
typedef double db; const int N = , M = ; //edge begin
struct node {
int next, to, len;
}edge[M<<];
int head[N], cnt=;
//edge end
int n, m, s, t; template<typename T>inline void read(T &_) {
_=;bool __=;char ___=getchar();
while(___<''||___>''){__|=(___=='-');___=getchar();}
while(___>=''&&___<=''){_=(_<<)+(_<<)+(___^);___=getchar();}
_=__?-_:_;
} template<class T>inline void get_max(T &_, T __) { _=_>__?_:__; }
template<class T>inline void get_min(T &_, T __) { _=_<__?_:__; }
template<class T>inline void Swap(T &_, T &__) { T ___=_;_=__;__=___; }
template<class T>inline T abs(T _) { return _>?_:-_; } inline void jb(int u, int v, int w) {
edge[++cnt].to=v;
edge[cnt].next=head[u];
edge[cnt].len=w;
head[u]=cnt;
} namespace Dinic {
int l, r, q[N], cur[N], dep[N], Max_flow;
inline bool bfs() {
memset(dep, , sizeof(dep));
memcpy(cur, head, sizeof(head));
l=r=; q[++r]=s; dep[s]=;
while(l<r) {
int u=q[++l];
for(int i=head[u];i;i=edge[i].next) {
int v=edge[i].to, w=edge[i].len;
if(dep[v]==&&w) dep[v]=dep[u]+, q[++r]=v;
}
}
if(dep[t]) return true;
else return false;
}
int dfs(int u, int min) {
if(min==||u==t) return min;
int flow=, f;
for(int &i=cur[u];i;i=edge[i].next) {
int v=edge[i].to, w=edge[i].len;
if(dep[v]==dep[u]+&&(f=dfs(v, std::min(min, w)))) {
flow+=f; min-=f;
edge[i].len-=f;
edge[i^].len+=f;
}
}
return flow;
}
inline void Dinic() {
int flow;
while(bfs())
while(flow=dfs(s, INF)) Max_flow+=flow;
printf("%d\n", Max_flow);
}
} int main() {
#ifndef ONLINE_JUDGE
freopen("Dinic.in","r",stdin);
freopen("Dinic.out","w",stdout);
#endif
int x, y, z;
read(n), read(m), read(s), read(t);
for(int i=;i<=m;i++) {
read(x), read(y), read(z);
jb(x, y, z), jb(y, x, );
}
Dinic::Dinic();
return ;
}
二分图:顾名思义,就是可以分成两个部分的图(把点分成两边,同一侧的点只能向另一侧的点连边);
二分图最大匹配:在边中选一个子集,使得每个点最多与该边集中的一个点相连,边数最多的子集即最大匹配;
如何求???
1.匈牙利算法(Hungarian method) : (brute_force) ———— 看代码
将点分为两部分(左右两边);(u在左边,v在右边)
mat[v]=u表示当前与v匹配的点为u;
每次dfs即寻求增广路;
//15owzLy1
//Hungary.cpp
//2018 10 10 17:04:04
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <vector>
#include <map>
#include <set>
#define lson tl, mid, rt<<1
#define rson mid+1, tr, rt<<1|1
#define pb(__) push_back(__)
#define fr() front()
#define bg() begin()
#define it iterator
#define INF 2100000000
typedef long long ll;
typedef double db; const int N = , M = ;
//edge bg;
struct node {
int next, to;
}edge[M*N];
int head[N], cnt=;
//edge end;
int mat[N], n, m, e;
bool vis[N]; template<typename T>inline void read(T &_) {
_=;bool __=;char ___=getchar();
while(___<''||___>''){__|=(___=='-');___=getchar();}
while(___>=''&&___<=''){_=(_<<)+(_<<)+(___^);___=getchar();}
_=__?-_:_;
} template<class T>inline void get_max(T &_, T __) { _=_>__?_:__; }
template<class T>inline void get_min(T &_, T __) { _=_<__?_:__; }
template<class T>inline void Swap(T &_, T &__) { T ___=_;_=__;__=___; }
template<class T>inline T abs(T _) { return _>?_:-_; } inline void jb(int u, int v) {
edge[++cnt].to=v;
edge[cnt].next=head[u];
head[u]=cnt;
} bool dfs(int u) {
vis[u]=true;
for(int i=head[u];i;i=edge[i].next) {
int v=edge[i].to;
if(vis[mat[v]]) continue;
if(mat[v]==||dfs(mat[v])) {
mat[v]=u; return true;
}
}
return false;
} inline int Hungary() {
int res=;
for(int i=;i<=n;i++) {
memset(vis, false, sizeof(vis));
if(dfs(i)) res++;
}
return res;
} int main() {
#ifndef ONLINE_JUDGE
freopen("Hungary.in","r",stdin);
freopen("Hungary.out","w",stdout);
#endif
int x, y;
read(n), read(m), read(e);//n, m为左右两边点的个数,e为边数
while(e--) {
read(x), read(y);
if(y>m) continue;
jb(x, y);
}
printf("%d\n", Hungary());
return ;
}
2.与网络流有何关系????
将源点和左边的点相连,右边的点与汇点相连,流量设为1;
左右点之间的边流量设为一个大于等于1的整数;
此时求出最大流,即为最大匹配;
感性理解一下:最大匹配是在边集中选出一个子集;一个点与该子集中的边相连,与该点与源点或者汇点所连边的流量流满是等效的;
建边过程:
inline void jb(int u, int v, int w) {
edge[++cnt].to=v;
edge[cnt].next=head[u];
edge[cnt].len=w;
head[u]=cnt;
}
int main() {
int x, y, z;
read(n), read(m), read(s), read(t);
for(int i=;i<=m;i++) {
read(x), read(y), read(z);
jb(x, y, z), jb(y, x, );
}
Dinic::Dinic();
return ;
}
网络(最大)流初步+二分图初步 (浅谈EK,Dinic, Hungarian method:]的更多相关文章
- 浅谈JAVA中如何利用socket进行网络编程(二)
转自:http://developer.51cto.com/art/201106/268386.htm Socket是网络上运行的两个程序间双向通讯的一端,它既可以接受请求,也可以发送请求,利用它可以 ...
- 算法模板——Dinic网络最大流 2
实现功能:同Dinic网络最大流 1 这个新的想法源于Dinic费用流算法... 在费用流算法里面,每次处理一条最短路,是通过spfa的过程中就记录下来,然后顺藤摸瓜处理一路 于是在这个里面我的最大流 ...
- 浅谈通信网络(三)——TCP/IP协议
简介 Transmission Control Protocol/Internet Protocol的简写,中译名为传输控制协议/因特网互联协议,又名网络通讯协议,是Internet最基本的协议.In ...
- Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理
Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理 转自:https://www.jianshu.com/p/2b71ea919d49 本系列文章首发于我的个人博 ...
- 虚拟化构建二分图(BZOJ2080 题解+浅谈几道双栈排序思想的题)
虚拟化构建二分图 ------BZOJ2080 题解+浅谈几道双栈排序思想的题 本题的题解在最下面↓↓↓ 不得不说,第一次接触类似于双栈排序的这种题,是在BZOJ的五月月赛上. [BZOJ4881][ ...
- 浅谈最大流的Dinic算法
PART 1 什么是网络流 网络流(network-flows)是一种类比水流的解决问题方法,与线性规划密切相关.网络流的理论和应用在不断发展,出现了具有增益的流.多终端流.多商品流以及网络流的分解与 ...
- 浅谈Hybrid技术的设计与实现第三弹——落地篇
前言 接上文:(阅读本文前,建议阅读前两篇文章先) 浅谈Hybrid技术的设计与实现 浅谈Hybrid技术的设计与实现第二弹 根据之前的介绍,大家对前端与Native的交互应该有一些简单的认识了,很多 ...
- 浅谈HTTPS以及Fiddler抓取HTTPS协议
最近想尝试基于Fiddler的录制功能做一些接口的获取和处理工作,碰到的一个问题就是简单连接Fiddler只能抓取HTTP协议,关键的登录请求等HTTPS协议都没有捕捉到,所以想让Fiddler能够同 ...
- Android性能优化的浅谈
一.概要: 本文主要以Android的渲染机制.UI优化.多线程的处理.缓存处理.电量优化以及代码规范等几方面来简述Android的性能优化 二.渲染机制的优化: 大多数用户感知到的卡顿等性能问题的最 ...
随机推荐
- SkylineGlobe7.0.1版本 支持SQLite(*.sqlite;*.db)数据库
SQLite,是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了 ...
- 1-STM32物联网开发WIFI(ESP8266)+GPRS(Air202)系统方案安全篇(来看一下怎么样监听网络数据,监听电脑上位机软件的数据)
首先安装网络监听软件 运行这个软件 这个软件安装到电脑上,默认是监听咱电脑上的网络通信 咱们先监听电脑的软件的网络通信数据,然后再说怎么监听Wi-Fi和APP的软件的网络通信数据 咱就监听咱基础篇的 ...
- .NET 开源项目 Polly 介绍
今天介绍一个 .NET 开源库:Polly,它是支持 .NET Core 的,目前在 GitHub 的 Star 数量已经接近 5 千,它是一个强大且实用的 .NET 库. Polly 介绍 官方对 ...
- 【Swift 3.0】iOS 国际化切换语言
有的 App 可能有切换语言的选项,结合系统自动切换最简单的办法: fileprivate var localizedBundle: Bundle = { return Bundle(path: Bu ...
- Python--day02(编程语言、运行python代码、变量)
day01主要内容回顾 1.进制转换: 二进制: 1111 0101 1010 十六进制 f 5 a 2.内存分布:堆区 和 栈区 外来人只能访问栈区的数据 ...
- vue-cli的跨域配置(自己总结)
- js对内容进行编码(富文本编辑器使用居多)
escape(string)函数可对字符串进行编码,这样就可以在所有的计算机上读取该字符串. 使用unescape(string) 对 escape() 编码的字符串进行解码.
- bzoj 4260: Codechef REBXOR (01 Trie)
链接: https://www.lydsy.com/JudgeOnline/problem.php?id=4260 题面: 4260: Codechef REBXOR Time Limit: 10 S ...
- bzoj4671: 异或图——斯特林反演
[BZOJ4671]异或图 - xjr01 - 博客园 考虑先算一些限制少的情况 gi表示把n个点的图,划分成i个连通块的方案数 连通块之间不连通很好处理(怎么处理看下边),但是内部必须连通,就很难办 ...
- centos7下tomcat8.5安装部署与优化
转自:https://www.cnblogs.com/busigulang/articles/8529719.html centos 7 Tomcat 8.5 的安装及生产环境的搭建调优 一 安装to ...