模板:网络流(Dinic算法)

文章目录

  • 1.网络最大流
    • 题目描述
    • 解析
      • 反悔边
      • 分层(避免环流)
      • 时间优化
    • 代码
  • 2.费用流
    • 描述
    • 解析
    • 代码

1.网络最大流

洛谷P3376

题目描述

在这里插入图片描述
给出一个网络图,以及其源点和汇点,求出其网络最大流。

解析

网络流的思想就是在原有的基础上不断进行增广
基于一个贪心的思路,先bfs判断是否存在增广路,再通过dfs增广

反悔边

但显然贪心会出错(比如当前终点通过其他点来使用会更优时)
所以就引入了反悔边
就是与所给边方向相反,一开始容量为0
增广使用边时除了把改变的边容量减去流量,再把反向边加上同样的流量即可
这样以后在必要时,就可以通过走反悔边的方式撤销之前的错误决策
举个例子
在这里插入图片描述
从S到T
如果贪心的走。先让2的10给了4
但实际上应该是2给5,3给4最优
那么我们就在2给4时使4到2的边容量从0加到10
这样在计算3这个点时就会顺着1-3-4-2-5-T走到终点
2-4与4-2流量都为10,等价于把一开始2到4这步操作撤销了

分层(避免环流)

为了避免dfs环流死循环的情况,我们要把这个图先分一下层
比如上图就是:

1层:S
2层:2 3
3层:4 5
4层 T

强制让dfs只能走到层数+1的点

时间优化

只是这么写的话会T掉一个点(也可能是我太菜常数太大。。。
考虑能否优化

我们发现,每次bfs之后的多次dfs增广中,这个图的分层结构是固定的
每个点尝试走的出边可能有一些在之前几次dfs已经用过,再枚举时其实已经得不到更多的流了
所以我们每次dfs时到每一个点就从上次dfs枚举到的出边开始枚举就行了
但注意,重新bfs后,图的结构改变,之前没用的边可能又能有流了
所以要重新从头枚举

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=300;
const int M=15500;struct node{int to,nxt;ll cap;
}p[M];
int fi[N],cnt=-1;
void addline(int x,int y,ll v){p[++cnt]=(node){y,fi[x],v};fi[x]=cnt;
}int n,m,s,t;
int a,b,c,d;int dis[N];
int cur[N];
void print(){for(int i=1;i<=n;i++) printf("%d ",dis[i]);printf("\n");}
int bfs(){queue<int>q;q.push(s);memset(dis,0,sizeof(dis));dis[s]=1;while (!q.empty()){int x = q.front();q.pop();for (int i = cur[x]= fi[x];~i;i = p[i].nxt){int to = p[i].to;if (dis[to]||!p[i].cap) continue;dis[to] = dis[x] + 1;q.push(to);}}return dis[t];
}
ll dfs(int x,ll lim){if(x==t||!lim) return lim;
//	printf("%d\n",x);ll res=0;for(int &i=cur[x];~i&&lim;i=p[i].nxt){int to=p[i].to;if(dis[to]!=dis[x]+1) continue;ll f=dfs(to,min(p[i].cap,lim));lim-=f;res+=f;p[i].cap-=f;p[i^1].cap+=f;}return res;
}
ll dinic(){ll ans=0,flow;while(bfs()){while(flow=dfs(s,2e15)) ans+=flow;}return ans;
}
int main(){memset(fi,-1,sizeof(fi));scanf("%d%d",&m,&n);s=1;t=n;for(int i=1;i<=m;i++){scanf("%d%d%d",&a,&b,&c);addline(a,b,c);addline(b,a,0);}printf("%lld",dinic());
}
/*
4 5 4 3
4 2 30
4 3 20
2 3 20
2 1 30
1 3 40
*/

2.费用流

洛谷P3381

描述

和最大流类似
只是每条边加了一个单位流的费用
求在最大流的前提下的最小费用方案

解析

上一题搞完这题就好多了
由于要求最小费用,把增广的bfs改为spfa跑费用的最短路
更新时记录路径
寻找路径上流量最小的值
然后累加费用即可

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=5500;
const int M=55000;struct node{int to,nxt;ll cap,v;
}p[M<<1];
int fi[N],cnt=-1;
void addline(int x,int y,ll w,ll v){p[++cnt]=(node){y,fi[x],w,v};fi[x]=cnt;
}int n,m,s,t;
int a,b,c,d;int dis[N];
int pre[N],from[N];
int vis[N];
bool spfa(){pre[t]=0;memset(dis,63,sizeof(dis));memset(vis,0,sizeof(vis));queue<int>q;q.push(s);vis[s]=1;dis[s]=0;while(!q.empty()){int now=q.front();q.pop();vis[now]=0;
//		printf("now=%d");for(int i=fi[now];~i;i=p[i].nxt){int to=p[i].to;if(p[i].cap==0) continue;if(dis[to]>dis[now]+p[i].v){dis[to]=dis[now]+p[i].v;pre[to]=now;from[to]=i;if(!vis[to]){vis[to]=1;q.push(to);}}}}return pre[t];
}
void dinic(){ll flow=0,v=0,tmp;while(spfa()){tmp=2e15;for(int i=t;i!=s;i=pre[i]) tmp=min(tmp,p[from[i]].cap);flow+=tmp;for(int i=t;i!=s;i=pre[i]){v+=tmp*p[from[i]].v;p[from[i]].cap-=tmp;p[from[i]^1].cap+=tmp;}}printf("%lld %lld",flow,v);return;
}
int main(){memset(fi,-1,sizeof(fi));scanf("%d%d%d%d",&n,&m,&s,&t);for(int i=1;i<=m;i++){scanf("%d%d%d%d",&a,&b,&c,&d);addline(a,b,c,d);addline(b,a,0,-d);}dinic();return 0;
}
/*
4 5 4 3
4 2 30
4 3 20
2 3 20
2 1 30
1 3 40
*/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/318517.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NC51272 棋盘覆盖

题目&#xff1a; 给出一张nn(n≤100) 的国际象棋棋盘&#xff0c;其中被删除了一些点&#xff0c;问可以使用多少1*2的多米 诺骨牌进行掩盖。 题解&#xff1a; 先进行黑白染色&#xff0c;相邻的两个黑白就是一个骨牌&#xff0c;又因为一个格子不能放多个骨牌&#xff0c;…

微软推出 VS Code 新特性,为 TypeScript 和 JavaScript 用户提供 AI 辅助开发功能

除了开发人员非常喜欢的IntelliSense和代码完成之外&#xff0c;今年早些时候&#xff0c;微软还发布了IntelliCode&#xff0c;提供了一组 AI 辅助开发功能。VS Code 团队现在宣布了一项新的实验性扩展&#xff0c;将 IntelliCode 带给了 TypeScript 和 JavaScript 用户。VS C…

NC107617 poj3020 Antenna Placement

问题&#xff1a; n * m的矩阵&#xff0c;有一些障碍点&#xff0c;用12的骨牌覆盖所有非障碍点 (12骨牌可重叠&#xff0c;骨牌可越界&#xff0c;骨牌可延伸到障碍点) 问最少需要 多少个。 题解&#xff1a; • 尽量用一个骨牌覆盖两个格子&#xff0c;覆盖不了了再重叠使…

货车运输(洛谷P1967)(倍增)

传送门 文章目录题目描述题目解析代码题目描述 题目解析 本题如果告诉你&#xff0c;城市形成了一棵树&#xff0c;是不是就迎刃而解了呢? 本题的关键就是把稠密图转化为一片森林&#xff08;就是可能有很多棵树啦&#xff09; 怎么转化呢? 考虑哪些边是没用的 如果AB已经可…

.NET Core实战项目之CMS 第十一章 开发篇-数据库生成及实体代码生成器开发

上篇给大家从零开始搭建了一个我们的ASP.NET Core CMS系统的开发框架&#xff0c;具体为什么那样设计我也已经在第十篇文章中进行了说明。不过文章发布后很多人都说了这样的分层不是很合理&#xff0c;什么数据库实体应该跟仓储放在一起形成领域对象&#xff0c;什么ViewModel应…

第1节 连通性强连通、割点和桥(一)

文章目录无向图割点、桥、双连通分量Tarjan算法求割点和桥&#xff08;割边&#xff09;代码&#xff1a;边双连通分量 和 点双连通分量代码边双连通分量 和 点双连通分量 的缩点有向图的弱连通与强连通强连通分量Kosaraju算法Tarjan算法代码&#xff1a;无向图割点、桥、双连通…

连通性(相关练习)

文章目录NC20603 [ZJOI2007]最大半连通子图题目&#xff1a;题解&#xff1a;代码&#xff1a;NC50403 嗅探器题目&#xff1a;题解&#xff1a;代码&#xff1a;NC51269 Network of Schools题目&#xff1a;题解&#xff1a;代码&#xff1a;NC106972 Cow Ski Area题目&#x…

ASP.NET Core WebAPI中使用JWT Bearer认证和授权

为什么是 JWT BearerASP.NET Core 在 Microsoft.AspNetCore.Authentication 下实现了一系列认证, 包含 Cookie, JwtBearer, OAuth, OpenIdConnect 等,Cookie 认证是一种比较常用本地认证方式, 它由浏览器自动保存并在发送请求时自动附加到请求头中, 更适用于 MVC 等纯网页系统的…

网络流专题(最大流与费用流)(一)

流量网络 • 想要将一些水从S运到T&#xff0c;必须经过一些水站&#xff0c;链接水站的是管道&#xff0c;每条管道都有它的最大能容纳的水量&#xff0c;求最多S到T能流多少流量。 基本概念 • 这是一个典型的网络流模型。我们先了解网络流的有关定义和概念。 • 若有向图G(…

eShopOnContainers 看微服务 ①:总体概览

一、简介eShopOnContainers是一个简化版的基于.NET Core和Docker等技术开发的面向微服务架构的参考应用。该参考应用是一个简化版的在线商城/电子商务微服务参考示例应用。其包含基于浏览器的Web应用、基于Xamarin的Android、IOS、Windows/UWP 移动应用&#xff0c;以及服务端应…

网络流专题(最大流与费用流)例题总结

文章目录NC 106056 poj1459 Power Network题目大意&#xff1a;题解&#xff1a;NC213817 [网络流24题]最小路径覆盖问题题目&#xff1a;题解&#xff1a;例2&#xff1a;NC213818 [网络流24题]魔术球问题题目&#xff1a;题解&#xff1a;方法2&#xff1a;NC 213820 [网络流…

周期长度和(KMP)

文章目录题目描述解析问题总结代码题目描述 解析 我们可以看到 如果A是B的周期 那么B一定可以写成&#xff1a; A1A2A1 的形式 注意到&#xff1a;A1就是KMP中的公共前后缀 要使A最大&#xff0c;要使A1最短 也就是求最短公共前后缀 这怎么求呢&#xff1f; 我们注意到&#x…

计算几何基础-1

文章目录基本概念点与向量的运算精度问题线段&#xff0c;射线和直线点积&#xff1a;夹角叉积向量的极角旋转一个向量求三角形面积直线交点点到直线距离点在直线上的投影判断两条线段是否相交点与直线的位置关系点是否在直线左侧点是否在直线上点是否在线段上点与多边形的位置…

.net core i上 K8S(四).netcore程序的pod管理,重启策略与健康检查

目录1.pod管理2.重启策略3.健康检查4.进入容器正文上一章我们已经通过yaml文件将.netcore程序跑起来了&#xff0c;但还有一下细节问题可以分享给大家。1.pod管理1.1创建podkubectl create -f netcore-pod.yaml我们创建一个netcore-pod.yaml文件&#xff0c;内容如下&#xff1…

洛谷P2680:运输计划(倍增、二分、树上差分)

传送门 文章目录题目描述解析问题代码题目描述 解析 求最大值的最小值 容易想到二分 然后。。。就没有然后了。。。 看了题解 学会了一个新技能&#xff1a;树上差分 &#xff08;其实学长之前好像讲过。。。&#xff09; 一般的&#xff0c;对于一条A到B的路径&#xff0c;如…

计算几何基础-2

文章目录直线&#xff1a;图形&#xff1a;求垂足求两圆交点直线与圆交点多边形问题判断一个点是否在任意多边形内部Pick定理凸包求点集的凸包水平法&#xff1a;增量法&#xff1a;半平面半平面交求半平面交直线&#xff1a; struct Line{point p,v;Line(){}Line(point _p.po…

eShopOnContainers 看微服务 ②:配置 启动

一、什么是dockerDocker 是一个开源项目&#xff0c;通过把应用程序打包为可移植的、自给自足的容器&#xff08;可以运行在云端或本地&#xff09;的方式&#xff0c;实现应用程序的自动化部署。使用 Docker 的时候&#xff0c;需要创建一个应用或服务&#xff0c;然后把它和它…

判断整除(opj)(动态规划)

解析 与取模结合的动归&#xff0c;正常做即可 问题 眼瞎&#xff01;&#xff01;&#xff01; 这个序列的每个数都必须用到&#xff01;&#xff01;&#xff01; if(f[i-1][j]) f[i][j]1;上面这行就是不对的&#xff01;&#xff01;&#xff01; 头疼 仔细审题 opj的题…

[USACO09FEB]Revamping Trails G

题意&#xff1a; 约翰一共有 N 个牧场.由 MM 条布满尘埃的小径连接。小径可以双向通行。每天早上约翰从牧场 1 出发到牧场 N 去给奶牛检查身体。 通过每条小径都需要消耗一定的时间。约翰打算升级其中 K 条小径&#xff0c;使之成为高速公路。在高速公路上的通行几乎是瞬间完…

NET Core微服务之路:自己动手实现Rpc服务框架,基于DotEasy.Rpc服务框架的介绍和集成...

本篇内容属于非实用性&#xff08;拿来即用&#xff09;介绍&#xff0c;如对框架设计没兴趣的朋友&#xff0c;请略过。 快一个月没有写博文了&#xff0c;最近忙着两件事;一&#xff1a;阅读刘墉先生的《说话的魅力》&#xff0c;以一种微妙的&#xff0c;你我大家都会经常遇…