其他分享
首页 > 其他分享> > 网络流

网络流

作者:互联网

from
https://blog.csdn.net/qq_41357771/article/details/79416899

记录一下看这个blog学网络流的一些点.

一、网络流

C[u,v] capacity
F[u,v] flow
input : S 原点 source
output: T 汇点 target

二、网络流的基本性质

1.if F<=C ->水管就炸了

2.流量守恒
源头输入 = 汇点收到 的量

3.F是有方向的
F[u,v] = -F[v,u]

4.容量 = 流量 + 残量

三、最大流问题

如图1-1,给你一个容量网络,假设要把一些物品从S送到T,问你T最多能收到多少物品
在这里插入图片描述

图1-2,展示了一种可行方案,第一个数字表示流量,第二个表示容量。
在这里插入图片描述

这样的问题称为最大流问题(Maximum-Flow Problem)。
我们求解最大流问题有两种算法Edmonds-Karp和Dinic算法,利用增广路来求解。

1.Edmonds-Karp
我们先讲Edmonds-Karp算法,简称EK(我认为这种算法比Dinic慢)

如图1-3(红色表示当前选的路径),这个想法就是先找一条从S到T的可行路径,然后往这条路径上输入X个流量,X取决于这条路径上最小的流量(毋庸置疑,否则就将管道挤爆了)。
在这里插入图片描述

只要找到一条可行路径,就可以停下了。这时有人会问,如果这条路径的不是最理想的怎么办。这就用到反向的边了,如果有一条更优秀的,那么就会往回流,避免了这种情况,也就是网络流里很重要的一点。(想到这里,不禁开始膜拜那些大神了,这么优秀的方法都想的出来。Orz)

通过以上简单的讲述,这个算法基本讲完了,不过是多次BFS,然后将这条路径上所有的流量增加X。这就是Edmonds-Karp。

MAXN//点数
MAXE//边数 
struct ad(){
	int x,y,C,F;//表示从x到y的容量是C,流量是F。
}a[2*MAXE];//因为有反向边,所以边数*2
vector<int> G[MAXN];//建立边表,存的是[x,y]这条边在a中的ID
int que[MAXN];//队列
int upd[MAXN];//用于更新当前最小的残量,如果upd[x]=0,表示这个点没被遍历过。
int fa[MAXN];//存储路径,从fa[y]走向y,方便增加流量

void Add(int x,int y,int c,int i){//i从1~MAXE
	a[i]=xcw(x,y,c,0);G[x].push_back(i-1<<1);
	a[i]=xcw(y,x,0,0);G[y].push_back((i-1<<1)+1);
}
bool BFS(){
	hd=0;que[tl=1]=S;
	memset(upd,0,sizeof(upd));upd[S]=1e9;
	while(hd!=tl){
		int x=que[++hd],L=G[x].size();
		for(int j=0;j<L;j++){
			xcw E=a[G[x][j]];
			if(!upd[E.y]&&E.C>E.F) 
			upd[E.y]=min(upd[x],E.C-E.F),que[++tl]=E.y,fa[E.y]=G[x][j];
		}
		if(upd[T]) return 1;//如果走到T就返回真值
	}
	return 0;//没走到返回假值
}
int Edmonds_Karp(){
	int Flow=0;
	while(BFS()){
		for(int x=T;x^S;x=a[fa[x]].x)//枚举当前BFS走的路径
		a[fa[x]].F+=upd[T],//加上当前最小残量
		a[fa[x]^1].F-=upd[T];//相反边减去最小残量
		Flow+=upd[T];
	}
	return Flow;//返回答案
}

一个问题供大家思考:为什么a[i^1]就是i这条边的相反边?

2. Dinic
…pass

四、最大流最小割

最大流最小割定理:网络的最大流等于最小割

1.任意一个流都小于等于任意一个割
这个很好理解 自来水公司随便给你家通点水,构成一个流
恐怖分子随便砍几刀 砍出一个割
由于容量限制,每一根的被砍的水管子流出的水流量都小于管子的容量
每一根被砍的水管的水本来都要到你家的,现在流到外面 加起来得到的流量还是等于原来的流
管子的容量加起来就是割,所以流小于等于割
(sum(流) = 入(流) <= sum(容量) = 割?)
由于上面的流和割都是任意构造的,所以任意一个流小于任意一个割

2.构造出一个流等于一个割
当达到最大流时,根据增广路定理
残留网络中s到t已经没有通路了,否则还能继续增广
我们把s能到的的点集设为S,不能到的点集为T
构造出一个割集C[S,T],S到T的边必然满流 否则就能继续增广
这些满流边的流量和就是当前的流即最大流
把这些满流边作为割,就构造出了一个和最大流相等的割
???

3.最大流等于最小割
这是一个证明…

4.费用流
顾名思义,费用流指的是有边权的流,就是一条边既有流量,也有单位流量的代价。

其实很简单,我们最大流时每次BFS去找边,费用流时就用最短路找,是不是很简单啊。

但是要注意,建回流的边的时候边权为相反数。

最大权闭合子图

标签:int,upd,路径,网络,流量,Edmonds,fa
来源: https://blog.csdn.net/Eternitykc/article/details/112238690