题解 洛谷 P3376 【【模板】网络最大流】
本人很弱,只会Dinic、EK与Ford-Fulkerson...(正在学习ISAP...)
这里讲Dinic...
Dinic:与Ford-Fulkerson和的思路相似(话说好像最大流求解都差不多吧),也是使用深搜寻找增广路(至于增广路是什么,只要在学最大流而不是借鉴他人代码的应该都知道吧)。
但是(划重点),Dinic有一个十分不一样的地方(Dinic:我们不一样,不一样!),就是还用了**BFS**(是为了凑齐深搜广搜召唤神龙)!
BFS有什么用呢,除了使时间复杂度更上一层楼之外,还有什么用呢?
这就是Dinic的神奇之处了,BFS反而使时间复杂度降低,与EK看似肩并肩(EK:O(nm^2) Dinic:O(n^2m))。看上去是肩并肩了,实则在题目上,Dinic基本都比EK优秀,特别是二分图。
扯远了,继续讲Dinic的BFS的用处。
BFS是为了划分等级(周朝的分封制!),使得在找增广路时跳过一些对这条增广路没用的点,使DFS效率大大提高。
另外,代码还可以加上当前弧优化与多路增广使其更快。
多路增广,设置一个变量used,记录这条边的流量,就不用搜到就退了,最后满了再退出。
当前弧优化:设置一个数组,在BFS预处理中将它赋值head[i],就相当于邻接表里的head,但是(划重点)它的值是随着增广的时候所变小的,然后下次增广时就可以跳过已经用过的边。
献上我丑陋的代码:
#include<cstdio>
#define INF 0x3f3f3f3f
#define maxn 3000001
inline int read(){//快读
int r=,f=;
char c=getchar();
while(c<''||c>''){
if(c=='-')f=-;
c=getchar();
}
while(c>=''&&c<=''){
r=r*+c-'';
c=getchar();
}
return r*f;
}
void write(int x)//快速输出
{
if(x<)
putchar('-'),x=-x;
if(x>)
write(x/);
putchar(x%+'');
}
struct edge{
int v,c,nxt;
}e[*maxn];
//struct max_Fow{//本来写了结构体的
int S,T,N,head[maxn],q[maxn],cur[maxn],level[maxn],tot=,hd,tl,v;
inline void init(int s,int t,int n){//为结构体而写
S=s;
T=t;
N=n+;
for(register int i=;i<N;i++)//想想为什么不直接为0
head[i]=-;
}
inline void add_edge(int u,int v,int c){
e[tot]=(edge){v,c,head[u]};//为什么从0开始?
head[u]=tot++;
}
inline void add(int u,int v,int c){
add_edge(u,v,c);
add_edge(v,u,);//反向边
}
inline bool BFS(){
for(register int i=;i<N;i++){
cur[i]=head[i];//当前弧优化初始化
level[i]=;//等级初始化
}
q[]=S;
level[S]=;
hd=;tl=;
while(hd^tl){//广搜
hd++;
for(register int i=head[q[hd]];i!=-;i=e[i].nxt){
if(e[i].c&&!level[e[i].v]){
tl++;
level[e[i].v]=level[q[hd]]+;
q[tl]=e[i].v;
if(e[i].v==T)return true;//搜到就退
}
}
}
return false;//否则无法拓展到汇点
}
inline int min(int a,int b){//手写min
if(a<b)return a;
return b;
}
int DFS(int f,int u){
if(u==T)return f;
int d=,used=;//多路增广
for(int &i=cur[u];i!=-;i=e[i].nxt){//当前弧优化
if(e[i].c&&level[u]==level[e[i].v]-){
if((d=DFS(min(f-used,e[i].c),e[i].v))){
e[i].c-=d;
e[i^].c+=d;//为什么可以直接这样?
used+=d;//多路增广
}
}
}
if(!used)level[u]=;
return used;
}
inline int Dinic(){//求解
int max_flow=;
while(BFS()){
int d=;
while((d=DFS(INF,S)))
max_flow+=d;
}
return max_flow;
}
//}Flow;
int main(){
int n=read(),m=read(),s=read(),t=read(),i;
/*Flow.*/init(s,t,n);
for(i=;i<=m;i++){
int a=read(),b=read(),v=read();
/*Flow.*/add(a,b,v);
}
int ans=/*Flow.*/Dinic();
write(ans);
return ;
}
Q:为什么head[]初始值为-1更好?
A:因为开始值就会为0,xor1就等于+1或-1,那样又会少了一些判断,
并且,Dinic也可以做费用流,只要将广搜换为SPFA就行了
完结撒花!!!✿✿ヽ(°▽°)ノ✿
题解 洛谷 P3376 【【模板】网络最大流】的更多相关文章
- 【最大流ISAP】洛谷P3376模板题
题目描述 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点序号.汇点序号. 接下来M行每行 ...
- P3376 [模板] 网络最大流
https://www.luogu.org/blog/ONE-PIECE/wang-lao-liu-jiang-xie-zhi-dinic EK 292ms #include <bits/std ...
- 洛谷P3376【模板】网络最大流 ISAP
这篇博客写得非常好呀. 传送门 于是我是DCOI这一届第一个网络流写ISAP的人了,之后不用再被YKK她们嘲笑我用Dinic了!就是这样! 感觉ISAP是会比Dinic快,只分一次层,然后不能增广了再 ...
- [洛谷P3376题解]网络流(最大流)的实现算法讲解与代码
[洛谷P3376题解]网络流(最大流)的实现算法讲解与代码 更坏的阅读体验 定义 对于给定的一个网络,有向图中每个的边权表示可以通过的最大流量.假设出发点S水流无限大,求水流到终点T后的最大流量. 起 ...
- 洛谷 P1546 最短网络 Agri-Net
题目链接 https://www.luogu.org/problemnew/show/P1546 题目背景 农民约翰被选为他们镇的镇长!他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场.当 ...
- 洛谷P1546 最短网络 Agri-Net(最小生成树,Kruskal)
洛谷P1546 最短网络 Agri-Net 最小生成树模板题. 直接使用 Kruskal 求解. 复杂度为 \(O(E\log E)\) . #include<stdio.h> #incl ...
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
- 『题解』洛谷P3376 【模板】网络最大流
Problem Portal Portal1:Luogu Description 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. Input 第一行包含四个正整数\(N,M,S,T\),分 ...
- 洛谷 P3376 【模板】网络最大流 题解
今天学了网络最大流,EK 和 Dinic 主要就是运用搜索求增广路,Dinic 相当于 EK 的优化,先用bfs求每个点的层数,再用dfs寻找并更新那条路径上的值. EK 算法 #include< ...
随机推荐
- [置顶]
使用 maven 插件 maven-shade-plugin 对可执行 java 工程及其全部依赖 jar 进行打包
作者:chenzhou123520 出处:http://chenzhou123520.iteye.com/blog/1706242 使用 maven 插件 maven-shade-plugin 对 j ...
- 判断浏览器是PC设备还是移动设备
var browser={ versions:function(){ var u = navigator.userAgent, app = navigator.appVersion; return { ...
- webpack操作基础
webpack 是一个前端加载/打包工具,根据模块的依赖关系进行静态分析,并依根据规则生成对应的静态资源
- a.WHERE使用中单行子查询(适用于>,<,=,>=,<=等条件)
a.单行子查询(适用于>,<,=,>=,<=等条件) //查询工资最高的员工编号和员工名 select empno,ename from emp where ...
- Docker 管理工具的选择:Kubernetes 还是 Swarm?
[编者的话]选择Kubernetes 或者 Swarm 就像在将 Linux 桌面发行版的范围缩小到两个后选出一个最喜欢的.哪个更满足你的需要如何才是决定因素. [3 天烧脑式基于Docker的CI/ ...
- C#-入门思维导图
C#-入门思维导图 百度云盘 链接:http://pan.baidu.com/s/1jI5zMS2 密码:0ypc 如有错误,请告知我
- mysql_5.6.24_winx64 安装
1.将zip压缩文件放在一个文件夹中 2.将路劲加入path环境变量 3.注册系统服务 在C:\windows下建立一个ini文件 1 2 3 4 5 6 7 8 9 10 11 12 [client ...
- Activity嵌套多个Fragment实现横竖屏切换
一.上图 二.需求 最近项目遇到个横竖屏切换的问题.较为复杂.在此记之. 1.Activity中竖屏嵌套3个Fragment,本文简称竖屏FP1,FP2,FP3. 2.当中竖屏FP1与FP2能够切换为 ...
- 输入password登录到主界面,录入学生编号,排序后输出
n 题目:输入password登录到主界面,录入学生编号,排序后输出 n 1. 语言和环境 A.实现语言 C语言 B.环境要求 VC++ 6.0 n 2. 要求 请编写一个C语言程序.将若干学生编 ...
- poj_1952最大下降子序列,统计个数
其实不算难的一道题,但憋了我好久,嗯,很爽. #include<iostream> #include<cstdio> #include<string.h> #inc ...