最大流,最小费用最大流:解析 + 各种板子

网络流初步 + Edmond-Karp算法

网络流的基本概念

  • 源点,这个点只有流量的流出,没有流入。
  • 汇点,这个点只有流量的流入,没有流出。
  • 容量,每条有向边的最大可承受的流的理论大小。
  • 流量,每条有向边的最大可承受的流的实际大小。
  • 最大流,从源点可流入汇点的最大流量。

Edmond-Karp算法

1、如果可以找到增广的路径,取这条路径上的最小的容量作为当前的可增广的流量。

2、在这条增广的路径中的每一个有向边减去当前可增广的流量,同时在其反向边加上当前可增广的流量。

3、重复1的操作,如果不能找到可增广的路径,则说明,已经找到了最大流,输出答案即可。

为什么要在反向边上增加上当前可增广的流量。

毫无疑问这张图的最大流是4=2(1−>3−>4)+2(1−>2−>4)4 = 2(1 -> 3 -> 4) + 2(1 -> 2 -> 4)4=2(1>3>4)+2(1>2>4)

但是如果我们找寻的一条增广路径是2(1−>2−>3−>4)2(1 -> 2 -> 3 -> 4)2(1>2>3>4)之后,我们再也就找不到其他的增广路径了

但是如果我们在每一次取用这条边之后,在其反方向增加对应的反向边。

显然我们可以得到另一个增广路径2(1−>3−>2−>4)2(1 -> 3 -> 2 -> 4)2(1>3>2>4),这里我们得到的最大流,也是正确答案。

板子 + 例题

Flow Problem 题目链接

#include <bits/stdc++.h>using namespace std;const int INF = 0x3f3f3f3f;int maze[20][20], n, m;
int visit[20], pre[20];bool bfs(int st, int ed) {queue<int> q;memset(visit, 0, sizeof visit);q.push(st);visit[st] = 1;while(!q.empty()) {int temp = q.front();q.pop();if(temp == ed)  return true;for(int i = 1; i <= n; i++) {if(!visit[i] && maze[temp][i] > 0) {visit[i] = 1;q.push(i);pre[i] = temp;}}}return false;
}int max_flow(int st, int ed) {int ans = 0;while(bfs(st, ed)) {int now_max = INF;int p = ed;while(p != st) {now_max = min(now_max, maze[pre[p]][p]);p = pre[p];}p = ed;while(p != st) {maze[pre[p]][p] -= now_max;maze[p][pre[p]] += now_max;p = pre[p];}ans += now_max;}// cout << ans << endl;return ans;
}int main() {// freopen("in.txt", "r", stdin);int t, x, y, w;scanf("%d", &t);for(int cas = 1; cas <= t; cas++) {scanf("%d %d", &n, &m);memset(maze, 0, sizeof maze);for(int i = 0; i < m; i++) {scanf("%d %d %d", &x, &y, &w);maze[x][y] += w;}printf("Case %d: %d\n", cas, max_flow(1, n));}return 0;
}

最大流

Edmond-Karp

原版的是用邻接矩阵写的,太耗内存了,这里改成邻接表。

#include <bits/stdc++.h>using namespace std;const int N1 = 1e4 + 10, N2 = 2e5 + 10;
const int INF = 0x3f3f3f3f;int head[N1], to[N2], nex[N2], cap[N2], cnt;
int flow[N1], pre[N1], id[N1], n, m, s, t;void add(int x, int y, int w) {to[cnt] = y;nex[cnt] = head[x];cap[cnt] = w;head[x] = cnt++;
}void input() {scanf("%d %d %d %d", &n, &m, &s, &t);int x, y, w;for(int i = 0; i < m; i++) {scanf("%d %d %d", &x, &y, &w);add(x, y, w);add(y, x, 0);}
}void init() {memset(head, -1, sizeof head);cnt = 0;
}int max_flow() {int ans = 0;for(;;) {queue<int> q;memset(flow, 0, sizeof flow);flow[s] = INF;q.push(s);while(!q.empty()) {int temp = q.front();q.pop();for(int i = head[temp]; ~i; i = nex[i]) {if(!flow[to[i]] && cap[i] > 0) {flow[to[i]] = min(flow[temp], cap[i]);pre[to[i]] = temp;id[to[i]] = i;q.push(to[i]);}}if(flow[t]) break;}if(!flow[t])    break;int p = t;while(p != s) {cap[id[p]] -= flow[t];cap[id[p] ^ 1] += flow[t];p = pre[p];}ans += flow[t];}return ans;
}int main() {// freopen("in.txt", "r", stdin);init();input();printf("%d\n", max_flow());return 0;
}

Dinic

玄学的Dinic

#include <bits/stdc++.h>using namespace std;typedef long long ll;const int N1 = 1e4 + 10, N2 = 2e5 + 10;
const int INF = 0x3f3f3f3f;int head[N1], to[N2], nex[N2], cap[N2], cnt;
int now[N1];int dis[N1], n, m, s, t;void init() {memset(head, -1, sizeof head);cnt = 0;
}void add(int x, int y, int w) {to[cnt] = y;nex[cnt] = head[x];cap[cnt] = w;head[x] = cnt++;
}bool bfs() {memset(dis, -1, sizeof dis);queue<int> q;q.push(s);dis[s] = 0;now[s] = head[s];while(!q.empty()) {int temp = q.front();q.pop();if(temp == t)   return true;for(int i = head[temp]; ~i; i = nex[i]) {if(dis[to[i]] == -1 && cap[i]) {now[to[i]] = head[to[i]];dis[to[i]] = dis[temp] + 1;q.push(to[i]);}}}return false;
}ll dfs(int rt, ll f) {if(rt == t) return f;ll delta = f;for(int i = now[rt]; ~i; i = nex[i]) {now[rt] = i;if(dis[to[i]] == dis[rt] + 1) {int temp = dfs(to[i], min(delta, 1ll * cap[i]));cap[i] -= temp;cap[i ^ 1] += temp;delta -= temp;}if(delta == 0)  break;} return f - delta;
}ll Dinic() {ll ans = 0;while(bfs()) ans += dfs(s, 0x3f3f3f3f3f3f3f3f);return ans;
}int main() {// freopen("in.txt", "r", stdin);init();scanf("%d %d %d %d", &n, &m, &s, &t);int x, y, w;for(int i = 0; i < m; i++) {scanf("%d %d %d", &x, &y, &w);add(x, y, w);add(y, x, 0);}printf("%lld\n", Dinic());return 0;
}

最小费用最大流

SPFA

#include <bits/stdc++.h>using namespace std;const int N1 = 5e3 + 10, N2 = 1e5 + 10;
const int INF = 0x3f3f3f3f;int head[N1], to[N2], nex[N2], cap[N2], value[N2], cnt;int dis[N1], pre[N1], id[N1], flow[N1], visit[N1], n, m, s, t;void add(int x, int y, int f, int w) {to[cnt] = y;nex[cnt] = head[x];value[cnt] = w;cap[cnt] = f;head[x] = cnt++;
}bool spfa() {memset(visit, 0, sizeof visit);memset(dis, 0x3f, sizeof dis);queue<int> q;q.push(s);dis[s] = 0, visit[s] = 1, flow[s] = INF, pre[t] = -1;while(!q.empty()) {int temp = q.front();q.pop();visit[temp] = 0;for(int i = head[temp]; ~i; i = nex[i]) {if(cap[i] > 0 && dis[to[i]] > dis[temp] + value[i]) {dis[to[i]] = dis[temp] + value[i];flow[to[i]] = min(flow[temp], cap[i]);pre[to[i]] = temp;id[to[i]] = i;if(!visit[to[i]]) {q.push(to[i]);visit[to[i]] = 1;}}}}return  pre[t] != -1;
}int min_cost_and_max_flow() {int max_flow = 0, min_cost = 0;while(spfa()) {max_flow += flow[t];min_cost += flow[t] * dis[t];int p = t;while(p != s) {cap[id[p]] -= flow[t];cap[id[p] ^ 1] += flow[t];p = pre[p];}}printf("%d %d\n", max_flow, min_cost);
}void init() {memset(head, -1, sizeof head);cnt = 0;
}int main() {// freopen("in.txt", "r", stdin);init();scanf("%d %d %d %d", &n, &m, &s, &t);int x, y, f, w;for(int i = 0; i < m; i++) {scanf("%d %d %d %d", &x, &y, &f, &w);add(x, y, f, w);add(y, x, 0, -w);}min_cost_and_max_flow();return 0;
}

两个假的Dijkstra

洛谷模板题卡爆DIjkstra。

好像第一个稍优一点。

第一个假的Dijkstra

#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back
#define x first
#define y secondusing namespace std;typedef pair<int, int> PII;
const int N1 = 5e3 + 10;
const int INF = 0x3f3f3f3f;int dis[N1], h[N1], flow[N1], pre[N1], id[N1], visit[N1], n, m, s, t;struct Edge {int to, cap, value, rever;Edge(int _to, int _cap, int _value, int _rever) : to(_to), cap(_cap), value(_value), rever(_rever) {}
};vector<Edge> G[N1];void add(int x, int y, int f, int w) {Edge temp1 = Edge(y, f, w, G[y].size());Edge temp2 = Edge(x, 0, -w, G[x].size());G[x].pb(temp1);G[y].pb(temp2);
}int min_cost_and_max_flow() {int min_cost = 0, max_flow = 0;memset(dis, 0x3f, sizeof dis);for(;;) {priority_queue<PII, vector<PII>, greater<PII> > q;dis[s] = 0, flow[s] = INF;q.push(mp(0, s));while(!q.empty()) {PII temp = q.top();q.pop();if(visit[temp.y])   continue;visit[temp.y] = 1;int u = temp.y;for(int i = 0; i < G[u].size(); i++) {Edge v = G[u][i];if(v.cap > 0 && dis[v.to] > dis[u] + v.value + h[u] - h[v.to]) {dis[v.to] = dis[u] + v.value + h[u] - h[v.to];flow[v.to] = min(v.cap, flow[u]);pre[v.to] = u;id[v.to] = i;q.push(mp(dis[v.to], v.to));}}}if(visit[t] == 0)    break;max_flow += flow[t];for(int i = 1; i <= n; i++) {h[i] += dis[i];dis[i] = INF;visit[i] = 0;}min_cost += flow[t] * h[t];int p = t;while(p != s) {G[pre[p]][id[p]].cap -= flow[t];G[p][ G[pre[p]][id[p]].rever].cap += flow[t];p = pre[p];}}printf("%d %d\n", max_flow, min_cost);
}int main() {// freopen("in.txt", "r", stdin);scanf("%d %d %d %d", &n, &m, &s, &t);int x, y, f, w;for(int i = 0; i < m; i++) {scanf("%d %d %d %d", &x, &y, &f, &w);add(x, y, f, w);}min_cost_and_max_flow();return 0;
}

第二个假的Dijkstra

#include <bits/stdc++.h>
#define mp make_pairusing namespace std;typedef pair<int, int> PII;
const int N1 = 5e3 + 10, N2 = 1e5 + 10;
const int INF = 0x3f3f3f3f;int head[N1], to[N2], nex[N2], cap[N2], value[N2], cnt;int visit[N1], flow[N1], dis[N1], pre[N1], id[N1], h[N1], n, m, s, t;void init() {memset(head, -1, sizeof head);cnt = 0;
}void add(int x, int y, int f, int w) {to[cnt] = y;nex[cnt] = head[x];value[cnt] = w;cap[cnt] = f;head[x] = cnt++;
}int min_cost_and_max_flow() {int min_cost = 0, max_flow = 0;memset(dis, 0x3f, sizeof dis);for(;;) {priority_queue<PII, vector<PII>, greater<PII> > q;q.push(mp(0, s));flow[s] = INF, dis[s] = 0;while(!q.empty()) {int temp = q.top().second;q.pop();// if(temp == t)   break;if(visit[temp]) continue;visit[temp] = 1;// if(temp == t)   break;for(int i = head[temp]; ~i; i = nex[i]) {if(cap[i] > 0 && dis[to[i]] > dis[temp] + value[i] + h[temp] - h[to[i]]) {dis[to[i]] = dis[temp] + value[i] + h[temp] - h[to[i]];flow[to[i]] = min(flow[temp], cap[i]);pre[to[i]] = temp;id[to[i]] = i;q.push(mp(dis[to[i]], to[i]));}}}if(visit[t] == 0)   break;for(int i = 1; i < n; i++) {h[i] += dis[i];visit[i] = 0;dis[i] = INF;}max_flow += flow[t];min_cost += flow[t] * h[t];int p = t;while(p != s) {cap[id[p]] -= flow[t];cap[id[p] ^ 1] += flow[t];p = pre[p];}}printf("%d %d\n", max_flow, min_cost);  
}int main() {// freopen("in.txt", "r", stdin);init();scanf("%d %d %d %d", &n, &m, &s, &t);int x, y, f, w;for(int i = 0; i < m; i++) {scanf("%d %d %d %d", &x, &y, &f, &w);add(x, y, f, w);add(y, x, 0, -w);}min_cost_and_max_flow();return 0;
}

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

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

相关文章

Zend创始人离职原来早已安排好

前边我们报导过&#xff0c;PHP 兼 Zend 公司联合创始人 Zeev Suraski 宣布目前已经从工作了 20 年的 Zend 公司离职。2 日晚间&#xff0c;知名 PHP 开发者&#xff0c;同时也是 PHP JIT 主力鸟哥&#xff08;惠新宸&#xff09;在朋友圈中曝出猛料&#xff1a;原来一切都是安…

梯度下降:求线性回归

梯度下降的直线拟合 实现说明 给定若干个x,yx, yx,y并且求得一个最佳的yaxby ax byaxb&#xff0c;也就是二元一次方程组的解。 先放上给定的散点&#xff0c;以及求得的线性回归的直线的图片。 我个人认为&#xff0c;这里的梯度优化&#xff0c;就是通过一个关键式子los…

3分钟了解数据库事务

事务是由几个读取和修改数据的sql命令组成的&#xff0c;但是知道commit命令被执行之后&#xff0c;修改操作才被认为是正常的完成。显式事务常以Begin tran语句开头&#xff0c;以commit tran或者rollback tran语句结尾的。事务具有acid属性原子性&#xff08;atomicity&#…

WebClient, HttpClient, HttpWebRequest ,RestSharp之间的区别与抉择

NETCore提供了三种不同类型用于生产的REST API&#xff1a; HttpWebRequest;WebClient;HttpClient&#xff0c;开源社区创建了另一个名为RestSharp的库。如此多的http库&#xff0c;该怎样选择呢&#xff1f;01HttpWebRequest这是.NET创建者最初开发用于使用HTTP请求的标准类。…

.NetCore 2.1以后的HttpClient最佳实践

ASP.NET Core 2.1中出现一个新的HttpClientFactory功能&#xff0c;它有助于解决开发人员在使用HttpClient实例从其应用程序发出外部Web请求时可能遇到的一些常见问题。01介绍在.NETCore平台的2.1新增了HttpClientFactory&#xff0c;虽然HttpClient这个类实现了disposable&…

点分治(简要讲解 + 模板)

树上点分治 思想 两个点之间的距离无非就是两种关系&#xff1a;我们约定dis[i]dis[i]dis[i]表示这个点到当前根节点的距离 dis[u]dis[v]dis[u] dis[v]dis[u]dis[v]&#xff0c;在同一个根节点的不同子树上。dis[u]dis[v]dis[u] dis[v]dis[u]dis[v]&#xff0c;在同一个棵子…

在 alpine 中使用 NPOI

在 alpine 中使用 NPOIIntro在 .net 中常使用 NPOI 来做 Excel 的导入导出&#xff0c;NPOI 从 2.4.0 版本开始支持 .netstandard2.0&#xff0c;在 dotnet core 应用也可以用 DotNetCore.NPOI。对于 .NET Core 应用来说&#xff0c;如果没有特殊的需求&#xff0c;alpine 是最…

Educational Codeforces Round 16 C. Magic Odd Square 矩阵构造

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 给你一个奇数nnn&#xff0c;让你构造一个n∗nn*nn∗n的矩阵&#xff0c;矩阵的每个位置依次填上[1,n∗n]之内的数[1,n*n]之内的数[1,n∗n]之内的数&#xff0c;满足每行、每列、以及主对角线的和都是奇数。…

关于WCF、WebAPI、WebService之间的区别总结 分布式通信技术

早在1996年Gartner就前瞻性地提出了面向服务架构的思想(SOA)&#xff0c;SOA 的走红在很大程度上归功于 Web Service 标准的成熟和应用的普及。Service Oriented Ambiguity 中文一般理解为&#xff1a;面向服务架构&#xff0c;简称SOA&#xff0c;这个概念算得上微服务的鼻祖了…

.NET中的值类型与引用类型

.NET中的值类型与引用类型这是一个常见面试题&#xff0c;值类型(Value Type)和引用类型(Reference Type)有什么区别&#xff1f;他们性能方面有什么区别&#xff1f;TL;DR&#xff08;先看结论&#xff09;值类型引用类型创建位置栈托管堆赋值时复制值复制引用动态内存分配无需…

跨语言调用Hangfire定时作业服务

背景Hangfire允许您以非常简单但可靠的方式执行后台定时任务的工作。内置对任务的可视化操作。非常方便。但令人遗憾的是普遍都是业务代码和hagnfire服务本身聚合在一个程序中运行&#xff0c;极大的限制了hangfire的扩展和跨语言调用。所以萌生了开发一个支持restful api调用的…

可落地微服务on k8s的持续集成/部署方案

我们隔一流的软件生产工艺还有多远&#xff1f;在距离15000公里外&#xff0c;Amazon一年可以进行5000万次部署&#xff0c;在这一边某电商平台的研发部门里&#xff0c;让他们引以为傲的是他们正在进行“敏捷”开发模式&#xff0c;并对外号称他们是以每周为迭代来进行升级。时…

Codeforces Round #579 (Div. 3) F1. Complete the Projects (easy version) 排序 + 贪心

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 思路&#xff1a; 比较直观的想法就是对于bi≥0b_i\ge0bi​≥0的项目&#xff0c;我们将aia_iai​从小到大排序&#xff0c;让后依次加bib_ibi​&#xff0c;如果有取不到的&#xff0c;显然就无解。否则再看…

历久弥新 - 微软万亿市值背后的文化支撑(下)|DevOps案例研究

内容来源&#xff1a;DevOps案例深度研究-Microsoft文化支撑研究战队&#xff08;本文只展示部分PPT研究成果&#xff0c;更多细节请关注案例分享会&#xff0c;及本公众号。&#xff09;本案例内容贡献者&#xff1a;陈飞&#xff08;Topic Leader&#xff09;、陈雨卿、郭子奇…

架构杂谈《九》

微服务与轻量级通信机制微服务架构是一种架构模式&#xff0c;它提倡将单一应用程序划分成一组小的服务&#xff0c;服务之间胡亮协调、互相配合&#xff0c;为用户提供最终价值。在微服务架构中&#xff0c;服务与服务之间通信时&#xff0c;通常是通过轻量级的通信机制&#…

Codeforces Round #585 (Div. 2) E. Marbles 状压dp + 逆序对

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 思路&#xff1a; 考虑数列最终的状态一定是相同颜色在一起&#xff0c;所以我们发现他的颜色是有顺序的&#xff01;显然可以用状压dpdpdp来枚举颜色的顺序&#xff0c;但是又有问题了&#xff0c;你怎么确…

GitLab CI 自动部署netcore web api 到Docker

前端篇文章中&#xff0c;我们已经成功的将asp.net core webapi在Docker容器中运行&#xff0c;并且部署了一套自己的GitLab环境。.Net & Docker&#xff08;二&#xff09;5分钟快速用Docker部署你自己的GitLab.Net & Docker&#xff08;一&#xff09;在Docker容器上…

.net core 实现基于 cron 表达式的任务调度

.net core 实现基于 cron 表达式的任务调度Intro上次我们实现了一个简单的基于 Timer 的定时任务&#xff0c;详细信息可以看这篇文章 。但是使用过程中慢慢发现这种方式可能并不太合适&#xff0c;有些任务可能只希望在某个时间段内执行&#xff0c;只使用 timer 就显得不是那…

ASP.NET Core Identity自定义数据库结构和完全使用Dapper而非EntityFramework Core

前言原本本节内容是不存在的&#xff0c;出于有几个人问到了我&#xff1a;我想使用ASP.NET Core Identity&#xff0c;但是我又不想使用默认生成的数据库表&#xff0c;想自定义一套&#xff0c;我想要使用ASP. NE Core Identity又不想使用EntityFramework Core。真难伺候&…

什么是微服务?为什么你要用微服务?

前言最近几年微服务很火&#xff0c;大家都在建设微服务&#xff0c;仿佛不谈点微服务相关的技术&#xff0c;都显得不是那么主流了。近几年见识到身边朋友的很多公司和团队都在尝试进行微服务的改变&#xff0c;但很多团队并没有实际微服务踩坑经验&#xff0c;很多团队甚至强…