题解 洛谷 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< ...
随机推荐
- (1)安装----anaconda3下配置pyspark【单机】
1.确保已经安装jdk和anaconda3.[我安装的jdk为1.8,anaconda的python为3.6] 2.安装spark,到官网 http://spark.apache.org/downlo ...
- 说说Shell在代码重构中的应用
说说Shell在代码重构中的应用 出处信息 出处:http://blogread.cn/it/article/3426?f=wb 代码重构(Code refactoring)有时是很枯燥的,字符 ...
- qt 透明化方法汇总
一. QT 透明设置 背景,标题栏透明,下级Widget,painter绘出来的(比如,drawtext,drawline)不透明 QWidget window; window.setWindowFl ...
- VUE:项目的创建、编写、打包及规范检查
VUE:项目的创建.编写及打包 项目的创建 使用 vue-cli 创建模板项目(官方提供的脚手架工具) https://github.com/vuejs/vue-cli npm install -g ...
- centos7下搭建solr服务器
1.Solr的环境 Solr是java开发. 需要安装jdk. 安装环境Linux. 需要安装Tomcat. 1.2. 搭建步骤 第一步:把solr 的压缩包上传到Linux系统 第二步:解压solr ...
- Virtual Box 新建一个虚拟机安装系统(补充:WIN7 64 bit 系统虚拟机无法安装 64 bit 系统问题)
1.安装Virtual Box好后,点击新建 2.配置内存大小,这个根据自己需要配置就好 3.创建虚拟硬盘 这里选择固定分配.动态分配都可以,接下来就分配硬盘大小了 4.新建好后我们点击刚才建立的虚拟 ...
- 【codeforces 768F】Barrels and boxes
[题目链接]:http://codeforces.com/problemset/problem/768/F [题意] 让你把f个food和w个wine装在若干个栈里面; 每个栈只能装food或者是wi ...
- 数人云CTO解读Docker 1.12和金融业容器化
7月29日 数人云 在上海举办金融沙龙,邀请上交所和近二十家来自银行.保险.证券的IT技术专家一同探讨容器技术在金融业中的最佳实践.数人云CTO肖德时在会上将传统金融行业通过容器可以解决的四大问题做了 ...
- 利用VisualVM监视远程JVM
VisualVM介绍 VisualVM是集成了多个JDK命令工具的一个可视化工具,它主要用来监控JVM的运行情况,可以用它来查看和浏览Heap Dump.Thread Dump.内存对象实例情况.GC ...
- 怎样注冊 diskgroup 到集群
之前使用 renamedg 对 ora.CRS.dg 进行重命名ora.DUPCRS.dg 可是 renamedg 有个缺点就是无法将改动的信息同步到整个集群层面,并且改动前的dg 会依旧保留在集群 ...