题解 洛谷 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< ...
随机推荐
- (2016北京集训十三)【xsy1531】魔法游戏 - Nim游戏
题解: 好题!我的结论很接近正解了... 把一个数化成二进制,每次至少要拿走一位,最多全拿走,不能不拿.那么这就是一个经典的Nim问题了,子树异或起来就是根节点的答案,随便递推一下就行了. 代码: # ...
- 转载一遍比较好的,django2.1搭建博客教程
非常感谢这位博主,找了几个星期终于找到了 https://www.dusaiphoto.com/article/article-detail/4/
- PHP动态函数处理
public class Student{ public function speek($name){ echo 'my name is '.$name; } } $method='speek'; $ ...
- 关于samsung连接BLE设备的一些资料汇总和开发过程一些经验总结
1 忙了这么久,终于有时间把最近几个月弄的东西整理一下,顺便我的开发过程和经历. 被公司分到做一个蓝牙4.0的项目,对这种软硬结合的东西也比较感兴趣,所以很快投入到android蓝牙4.0的项目中来. ...
- Java基础学习总结(47)——JAVA输入输出流再回忆
一.什么是IO Java中I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列. Java的I/O流提供了 ...
- 讲一讲java异常及自定义异常
1.异常,说白了.两种,一种就是就是不能让代码通过编译的异常.另一种就是程序运行期间出现的异常.异常就是错误,只要出现异常,程序就不会向下运行了.就不会执行后面的代码了.这时候就可以通过显示statc ...
- 彻底理解tomcat是怎样多线程处理http请求并将代码执行到controller里的的
彻底理解tomcat是怎样多线程处理http请求并将代码执行到controller里的的 1.线程池,thread = threadPool.getThread(),thread.executeHtt ...
- java 日期和字符串互转,依据当天整天时间 得到当天最后一秒的日期时间
java 日期和字符串互转.依据当天整天时间 得到当天最后一秒的日期时间 package com.hi; import java.text.DateFormat; import java.text ...
- 推断CPU 是小端存储(Little endian)还是大端存储(Big endian)模式
第一个版本号: //return true in big-endian machines bool check_big_endian1() { int a = 0; int *p = &a; ...
- Centos yum 安装lamp PHP5.4版本号
centos 6.5 1.yum安装和源码编译在使用的时候没啥差别.可是安装的过程就大相径庭了,yum仅仅须要3个命令就能够完毕,源码须要13个包,还得加压编译.步骤非常麻烦,并且当做有时候会出错,源 ...