本文中  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. python小白——进阶之路——day1天---认识python和变量、注释

    ###-python的认知 89年开发的语言,创始人范罗苏姆(Guido van Rossum),别称:龟叔(Guido) (1)版本: python2.x原码不规范,重复较多 python3x:原码 ...

  2. Python的dnspython库使用指南

    因为平时在测试DNS的时候有些操作手动完成不方便,所以需要用到脚本,而在Python里dnspython这个用于DNS操作的库十分强大,但是无奈网上大部分资料只列举了少部分的用法,所以记录一下我平时使 ...

  3. JShell脚本工具

    JShell脚本工具是JDK9的新特性 什么时候会用到 JShell 工具呢,当我们编写的代码非常少的时候,而又不愿意编写类,main方法,也不愿意去编译和运行,这个时候可以使用JShell工具.启动 ...

  4. 【学习总结】GirlsInAI ML-diary day-18-下载/保存excel

    [学习总结]GirlsInAI ML-diary 总 原博github链接-day18 使用Python来操作excel文件 Excel的处理与DataFrame格式是分不开的 可以理解为DataFr ...

  5. 转:Flutter动画一

    1. 动画介绍 动画对于App来说,非常的重要.很多App,正是因为有了动画,所以才会觉得炫酷.移动端的动画库有非常的多,例如iOS上的Pop.web端的animate.css.Android端的An ...

  6. Tensorflow调试Bug解决办法记录

    1.ascii' codec can't encode characters in position 0-4: ordinal not in range(128) 原因是python2.X默认的编码是 ...

  7. Bugku 分析 中国菜刀

    解压之后得到了一个流量包,只有不到10KB,美滋滋 先抓重点,过滤出http,只有6条数据记录,3条post,3条response,3条post都是一样的 随便打开一条pos 是一个assert断言, ...

  8. python之pymongo

    引入 在这里我们来看一下Python3下MongoDB的存储操作,在本节开始之前请确保你已经安装好了MongoDB并启动了其服务,另外安装好了Python的PyMongo库. MongoDB 数据库安 ...

  9. react事件处理函数中绑定this的bind()函数

    问题引入 import React, { Component } from 'react'; import { Text, View } from 'react-native'; export def ...

  10. 基于Matlab实现多次最佳一致的函数逼近(类似求渐进函数)

    %%%做系统识别很重要,方法上完全符合系统识别最基础的理论 function [sun]=main(n) fplot(,],'r'); x=ones(n+,); :n+ x(j+)=cos(pi*(n ...