首页 > 其他分享 >最小费用最大流

最小费用最大流

时间:2024-10-21 20:44:04浏览次数:1  
标签:费用 最大 增广 int 最小 流量 网络 ... include

终于把自己搞蒙了
简而言之,最小费用最大流就是这样:
图论中的一种理论与方法,研究网络上的一类最优化问题 。很多系统中涉及流量问题,例如公路系统中车流量,网络中的数据信息流,供油管道的油流量等。我们可以将有向图进一步理解为“流网络”(flow network),并利用这样的抽象模型求解有关流量的问题。
显然我是完全没看懂的,那么,比如我们有一个交通网络如下图。
边上标的是可以通过的人。
现在我们要从1到5,最多有几个人?
如图:得出最多4人
这就是最大流。
那么,怎么求最大流呢?
求解网络流的基本思想就是每次寻找增广路(就是源点到汇点的一条可行路)然后ans+=增广路能流过的流量,更新剩余网络,然后再做增广路,直到做不出增广路。关于网络流入门最难理解的地方就是剩余网络了....为什么在找到一条增广路后...不仅要将每条边的可行流量减去增广路能流过的流量...还要将每条边的反向弧加上增广路能流过的流量.?..原因是在做增广路时可能会阻塞后面的增广路...或者说做增广路本来是有个顺序才能找完最大流的.....但我们是任意找的...为了修正...就每次将流量加在了反向弧上...让后面的流能够进行自我调整...剩余网络的更新(就在原图上更新就可以了)
(what?speak earth language!)反正我是没看懂的……..若有大神围观勿喷。
接下来蒟蒻给你们讲讲网络流最大流最简单也是最慢的一种EK算法:
我们设刚刚那个啥交通网络为图G,这个图是个有向图,不然做不了,记住这句话,后面有题目。
定义c函数为管道容量大小,就是火车上最多坐多少个人,f函数为管道的流量,就是火车身上现在做了几个人。
显然c函数要大于等于f函数的大小(不多说,水流多了管子会爆,其次,这是中国,不是印度,还是不能坐火车顶上的)。
这是图G的三个性质之一:容量限制,然后有个反对称性,就是流过去的f = 流回来的-f,
现在不懂没事,一会讲反向边的时候细讲,
第三个就是流守恒性,就是从源点出发的总流量等于到汇点的总流量,就是从1出发的人不能在火车上失踪了。
明白了这些,我现在来讲网络流中最难理解的东西:反向边
来个经典的图:

嗯,有向图吧,不多说了,初始是0号节点流向一号节点和四号节点(未画出)1->2->5->6->7
流量都是10,我们假设这条路径上都是满流,就是c = f 就是不能再流其他的流了,然后我们设定其他边上也是c = 10,4->5也有5的流量,如果按照EK算法中的bfs来说,为了找到一个最大流,2->3这条边都不会走,可能一开始找瓶颈把4,5入队,但是后面不断调整流量时,流量回被调成10,毕竟程序是为了寻找最大流,
所以说如果不把流过的边加上一个反向边4->5这个流量都不会被加入增广路,可能你还是没怎么理解,我先来介绍下残量网络,这样你会理解的更深。

红色的数字代表回流的量,2->3那条边我先暂时不标,在残留网络的中如果那么就给它连一条回去的边,先别问我为什么,慢慢来。连回去的边大小为增广路上流量的大小,原来的边为c-f,流量为0的边不在残量网络中出现。现在我们再来讲讲反相边到底是用来干嘛的,你看,如果给2->5加一条反相边,是不是4可以通过反相边到达汇点7,而原来的图是不行的因为5,6这条边已经满流,所以说,如果不加反相边,会有一条路都找不到,那不就很尴尬了,_。换句话说,加条反相边那就是给程序一个反悔的机会,现实中,反相边是不存在的,只是在程序中出现,实际上,这就相当于4->5的流量转给2->3,第一条路变成1,2,3,7,第二条路变成4,5,6,7,所以,是不是更好理解了呢?接下来,我来讲讲EK的代码。

//不要太在意代码风格啦。
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<cstdio>
#define For(a,b,c) for(a=b;a<=c;a++)
#include<queue>
#define inf 999999999
using namespace std;
const int maxn = 1010;
int rong[510][510],liu[510][510];
int p[maxn];
int m,n;
int pre[maxn];
int sum;
void internet() {
	queue<int> q;
	while(1) { //不断通过bfs来找增光路,然后ans+=增光路上的流量。
		int i,j;
		memset(p,0,sizeof(p));
		p[1]=inf;//这里的p数组有两个作用,一是用来标记是非访问过,其次是用来记增广路上的瓶颈。
		q.push(1);
		while(!q.empty()) {
			int ans=q.front();
			q.pop();
			For(i,1,n) {
				if(!p[i]&&liu[ans][i]<rong[ans][i]) {
					p[i]=min(p[ans],rong[ans][i]-liu[ans][i]);
					pre[i]=ans;//记录增广路。
					q.push(i);
				}
			}
		}
		if(!p[n]) {
			break;//如果n点找不到增光路,说明已经没增广路到汇点了。
		}
		sum+=p[n];
		int tmp=n;
		while(pre[tmp]) { //不断调整流量大小。
			liu[pre[tmp]][tmp]+=p[n];
			liu[tmp][pre[tmp]]-=p[n];
			tmp=pre[tmp];
		}
	}
}
int main() {
	int i,j,k;
	int x,y,z;
	while(scanf("%d%d",&m,&n)!=EOF) {
		sum=0;
		memset(pre,0,sizeof(pre));
		memset(rong,0,sizeof(rong));
		memset(liu,0,sizeof(liu));
		For(i,1,m) {
			scanf("%d%d%d",&x,&y,&z);
			rong[x][y]+=z;
		}
		internet();
		printf("%d\n",sum);
	}
	return 0;
}

标签:费用,最大,增广,int,最小,流量,网络,...,include
From: https://www.cnblogs.com/zan-mei-tai-yang/p/18490333

相关文章

  • 洛谷题单指南-字符串-P4735 最大异或和
    原题链接:https://www.luogu.com.cn/problem/P4735题意解读:已知长度为n的数组a[],要在l~r范围找到一个p,使得a[p]^a[p+1]^...^a[n]^x最大,求这个最大的异或值。解题思路:1、利用前缀和将问题转化设s[]是a[]的前缀异或数组,要计算a中一段范围l~r的异或,可以借助于s由于s[r]=a[0]^a[......
  • Leetcode 1584. 连接所有点的最小费用
    1.题目基本信息1.1.题目描述给你一个points数组,表示2D平面上的一些点,其中points[i]=[x_i,y_i]。连接点[x_i,y_i]和点[x_j,y_j]的费用为它们之间的曼哈顿距离:|x_i–x_j|+|y_i–y_j|,其中|val|表示val的绝对值。请你返回将所有点连接的最小总费用。只......
  • 最小体积拉取git仓库并保持可更新
    对于超大型的git仓库不需要提交只是拉取代码进行查看并希望保持代码更新,那么使用depth不仅能得到极小体积的仓库还能大大提速拉取时间拉取最小代码结论:功德+1,来自于掌门的用法,depth设置为300之后,基本上没碰到问题,git新手也可以完整拉取。拉取代码:gitclonehttp://git-inter......
  • 二分求操作后的最大最小中位数
    这类题是让你求对序列进行一系列操作之后的最小/最大中位数求最小中位数二分最小中位数,显然二分要符合mid越大越对,边界才能向下收缩。对于这个条件,我们选择计算小于等于当前mid的数才是对的,因为这样显然mid越大cnt越大,而符合这个条件,我们就不断收缩上界,直到达到第......
  • 小于n的最大数,记一道字节面试题
    packageclient;importjava.util.Arrays;publicclassMainTest{publicstaticvoidmain(String[]args){//TestcaseexamplesSystem.out.println(maxN(newint[]{0,1,2,3,4,5,6,7,8,9},235));//Expected:235System.o......
  • 线性可分支持向量机的原理推导【补充知识部分】9-10最大化函数max α,β L(x,α,β)关
    本文是将文章《线性可分支持向量机的原理推导》中的公式单独拿出来做一个详细的解析,便于初学者更好的理解。在主文章中,有一个部分是关于补充拉格朗日对偶性的相关知识,此公式即为这部分里的内容。公式9-10是基于公式9-9的进一步引申,它通过引入拉格朗日乘子,将约束优化问......
  • 【C++贪心】2086. 喂食仓鼠的最小食物桶数|1622
    本文涉及知识点C++贪心LeetCode2086.喂食仓鼠的最小食物桶数给你一个下标从0开始的字符串hamsters,其中hamsters[i]要么是:‘H’表示有一个仓鼠在下标i,或者’.’表示下标i是空的。你将要在空的位置上添加一定数量的食物桶来喂养仓鼠。如果仓鼠的左边或右边......
  • 分治法求最大连续子序列的积
    1.源代码#include<iostream>#include<vector>#include<string>#include<sstream>usingnamespacestd;intmax3(intnum1,intnum2,intnum3){   if(num1>num2){      num2=num1;   }   returnnum2>num3?num2:n......
  • 图的m着色问题与图的最大团问题的关系,以及利用这个关系改进最大团问题的上界
    图的m着色问题与图的最大团问题的关系一、图的m着色问题1.定义:给定无向连通图G=(V,E),其中V是顶点集合,E是边集合。用m种颜色对图中的每个顶点进行着色,使得任意两个相邻的顶点具有不同的颜色。目标是确定是否存在这样的着色方案,以及如果存在,找出一种具体的着色方式。2.目......
  • 111. 二叉树的最小深度
    思路递归时考虑几种情况:1.左右子树都为空,则最小深度=1(只有根节点)(也可理解为min(0,0)+1)2.左子树为空,右子树不空,则最小深度=右子树最小深度+13.左子树不为空,右子树为空,最小深度=左子树最小深度+14.左右子树不为空,最小深度=左右子树最小深度+1+1原因:递归的是左右子树,......