本文中  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:]的更多相关文章

  1. 浅谈JAVA中如何利用socket进行网络编程(二)

    转自:http://developer.51cto.com/art/201106/268386.htm Socket是网络上运行的两个程序间双向通讯的一端,它既可以接受请求,也可以发送请求,利用它可以 ...

  2. 算法模板——Dinic网络最大流 2

    实现功能:同Dinic网络最大流 1 这个新的想法源于Dinic费用流算法... 在费用流算法里面,每次处理一条最短路,是通过spfa的过程中就记录下来,然后顺藤摸瓜处理一路 于是在这个里面我的最大流 ...

  3. 浅谈通信网络(三)——TCP/IP协议

    简介 Transmission Control Protocol/Internet Protocol的简写,中译名为传输控制协议/因特网互联协议,又名网络通讯协议,是Internet最基本的协议.In ...

  4. Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理

    Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理 转自:https://www.jianshu.com/p/2b71ea919d49 本系列文章首发于我的个人博 ...

  5. 虚拟化构建二分图(BZOJ2080 题解+浅谈几道双栈排序思想的题)

    虚拟化构建二分图 ------BZOJ2080 题解+浅谈几道双栈排序思想的题 本题的题解在最下面↓↓↓ 不得不说,第一次接触类似于双栈排序的这种题,是在BZOJ的五月月赛上. [BZOJ4881][ ...

  6. 浅谈最大流的Dinic算法

    PART 1 什么是网络流 网络流(network-flows)是一种类比水流的解决问题方法,与线性规划密切相关.网络流的理论和应用在不断发展,出现了具有增益的流.多终端流.多商品流以及网络流的分解与 ...

  7. 浅谈Hybrid技术的设计与实现第三弹——落地篇

    前言 接上文:(阅读本文前,建议阅读前两篇文章先) 浅谈Hybrid技术的设计与实现 浅谈Hybrid技术的设计与实现第二弹 根据之前的介绍,大家对前端与Native的交互应该有一些简单的认识了,很多 ...

  8. 浅谈HTTPS以及Fiddler抓取HTTPS协议

    最近想尝试基于Fiddler的录制功能做一些接口的获取和处理工作,碰到的一个问题就是简单连接Fiddler只能抓取HTTP协议,关键的登录请求等HTTPS协议都没有捕捉到,所以想让Fiddler能够同 ...

  9. Android性能优化的浅谈

    一.概要: 本文主要以Android的渲染机制.UI优化.多线程的处理.缓存处理.电量优化以及代码规范等几方面来简述Android的性能优化 二.渲染机制的优化: 大多数用户感知到的卡顿等性能问题的最 ...

随机推荐

  1. [Spark]如何设置使得spark程序不输出 INFO级别的内容

    Spark程序在运行的时候,总是输出很多INFO级别内容 查看了网上的一些文章,进行了试验. 发现在 /etc/spark/conf 目录下,有一个 log4j.properties.template ...

  2. 即将发布的 ASP.NET Core 2.2 会有哪些新玩意儿?

    今年 6 月份的时候时候 .NET 团队就在 GitHub 公布了 ASP.NET Core 2.2 版本的 Roadmap(文末有链接),而前两天 ASP.NET Core 2.2 预览版 2 已经 ...

  3. PS绘制飘逸彩色丝带教程

    一.新建一个大小适当的图像,点击工具栏上的钢笔工具,使用形状图层来绘制出下图的形状. 二.把形状所在层的填充设为0%,填充设成0是不会影响到图层的,不像不透明度那样会影响图层样式的效果. 三.双击丝带 ...

  4. docker(一) Centos7下安装docker

    docker(一) Centos7下安装dockerdocker(二) windows10下安装dockerdocker(三) 镜像和容器常用命令 docker(四) 使用Dockerfile构建镜像 ...

  5. 用UE4蓝图制作FPS_零基础学虚幻4第二季

    课时1:案例演示 05:12 课时2:工程准备 07:35 (把一个项目从一个工程移动到另一个工程) 1.新建一个空白工程,不包含初学者内容 2.选择我们要复制的工程,按右键,如下图: 复制到新工程的 ...

  6. 舵机&数据处理&stm32内存之堆栈溢出(遇到的问题)

    产品名称:TOWER PRO(辉盛)大扭力舵机MG996R (MG995升级产品)6v/11Kg厂家编号:MG996R产品净重: 55g产品尺寸: 40.7*19.7*42.9mm产品拉力: 9.4k ...

  7. 当同时安装Python2和Python3后,如何兼容并切换使用详解(比如pip使用)

    由于历史原因,Python有两个大的版本分支,Python2和Python3,又由于一些库只支持某个版本分支,所以需要在电脑上同时安装Python2和Python3,因此如何让两个版本的Python兼 ...

  8. Vivado如何使用命令行创建工程

    前言 vivado中采用TCL脚本语言来作为其命令解释语言.除去可以普通的图形界面流程还可以使用tcl脚本创建工程并导入相关源文件.   流程 1.首先还是要打开vivado图形主界面. 2.在某路径 ...

  9. Codeforces 1077F2 Pictures with Kittens (hard version)(DP+单调队列优化)

    题目链接:Pictures with Kittens (hard version) 题意:给定n长度的数字序列ai,求从中选出x个满足任意k长度区间都至少有一个被选到的最大和. 题解:数据量5000, ...

  10. Linux-服务器创建swap交换分区

    服务器 swap 交换分区制作 作用:‘提升‘ 内存的容量,防止OOM(Out Of Memory) 查看当前的交换分区 # cat /proc/swaps # free -m # swapon -s ...