网络流—Edmonds-Karp 最短增广路算法(最大流)

网络流————Edmonds-Karp 最短增广路算法 


■求最大流的过程,就是不断找到一条源到汇的路径,然后构建残余网络,再在残余网络上寻找新的路径,使总流量增加,然后形成新的残余网络,再寻找新路径…..直到某个残余网络上找不到从源到汇的路径为止,最大流就算出来了。 

■每次寻找新流量并构造新残余网络的过程,就叫做寻找流量的“增广路径”,也叫“增广” 

现在假设每条边的容量都是整数  ,这个算法每次都能将流至少增加1   

由于整个网络的流量最多不超过 图中所有的边的容量和C,从而算法会结束 

复杂度

找增广路径的算法可以用dfs,复杂度为边数m+顶点数n ,Dfs 最多运行C次 ,所以时间复杂度为C*(m+n) =C* n^2 
这个算法实现很简单  
但是注意到在图中C可能会非常大  

因此在每次增广的时候,选择从源到汇的具有最少边数的增广路径,即不是通过dfs寻找增广路径,而是通过bfs寻找增广路径。 

这就是Edmonds-Karp 最短增广路算法 

已经证明这种算法的复杂度上限为nm^2 (n是点数,m是边数) 


Drainage Ditches

 POJ - 1273 

Every time it rains on Farmer John's fields, a pond forms over Bessie's favorite clover patch. This means that the clover is covered by water for awhile and takes quite a long time to regrow. Thus, Farmer John has built a set of drainage ditches so that Bessie's clover patch is never covered in water. Instead, the water is drained to a nearby stream. Being an ace engineer, Farmer John has also installed regulators at the beginning of each ditch, so he can control at what rate water flows into that ditch. 
Farmer John knows not only how many gallons of water each ditch can transport per minute but also the exact layout of the ditches, which feed out of the pond and into each other and stream in a potentially complex network. 
Given all this information, determine the maximum rate at which water can be transported out of the pond and into the stream. For any given ditch, water flows in only one direction, but there might be a way that water can flow in a circle. 

Input

The input includes several cases. For each case, the first line contains two space-separated integers, N (0 <= N <= 200) and M (2 <= M <= 200). N is the number of ditches that Farmer John has dug. M is the number of intersections points for those ditches. Intersection 1 is the pond. Intersection point M is the stream. Each of the following N lines contains three integers, Si, Ei, and Ci. Si and Ei (1 <= Si, Ei <= M) designate the intersections between which this ditch flows. Water will flow through this ditch from Si to Ei. Ci (0 <= Ci <= 10,000,000) is the maximum rate at which water will flow through the ditch.

Output

For each case, output a single integer, the maximum rate at which water may emptied from the pond.

Sample Input

5 4
1 2 40
1 4 20
2 4 20
2 3 30
3 4 10

Sample Output

50

赤裸裸的网络流题目。给定点数,边数,每条边的容量,以及源点,汇点,求最大流。 


#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;

int G[300][300];
int Prev[300]; //路径上每个节点的前驱节点
bool Visited[300];
int n, m; //m是顶点数目,顶点编号从1开始 1是源,m是汇, n是边数

unsigned Augment(void)
{
	int v;
	int i;
	deque<int> q;
	memset(Prev, 0, sizeof(Prev));
	memset(Visited, 0, sizeof(Visited));
	Prev[1] = 0;
	Visited[1] = 1;
	q.push_back(1);
	bool bFindPath = false;
	
	//用bfs寻找一条源到汇的可行路径
	while (!q.empty()){
		v = q.front();
		q.pop_front();
		for (i = 1; i <= m; i++){
			if (G[v][i] > 0 && Visited[i] == 0){
				//必须是依然有容量的边,才可以走
				Prev[i] = v;
				Visited[i] = 1;
				if (i == m){
					bFindPath = true;
					q.clear();
					break;
				}else
					q.push_back(i);
			}
		}
	}

	if (!bFindPath)
		return 0;
	int nMinFlow = 999999999;
	v = m;
	//寻找源到汇路径上容量最小的边,其容量就是此次增加的总流量
	while (Prev[v]){
		nMinFlow = min(nMinFlow, G[Prev[v]][v]);
		v = Prev[v];
	}
	//沿此路径添加反向边,同时修改路径上每条边的容量
	v = m;
	while (Prev[v]){
		G[Prev[v]][v] -= nMinFlow;
		G[v][Prev[v]] += nMinFlow;
		v = Prev[v];
	}
	return nMinFlow;
}

int main(void)
{
	while (~scanf("%d%d", &n, &m)){
		//m是顶点数目,顶点编号从1开始
		int i, j, k;
		int s, e, c;
		memset(G, 0, sizeof(G));
		for (i = 0; i < n; i++){
			scanf("%d%d%d", &s, &e, &c);
			G[s][e] += c; //两点之间可能有多条边
		}
		
		unsigned int MaxFlow = 0;
		unsigned int aug;

		while (aug = Augment())
			MaxFlow += aug;
		cout << MaxFlow << endl;
	}
	return 0;
}

 

全部评论

相关推荐

面试官全程关摄像头1.自我介绍一下2.React和Vue哪个更熟悉一点3.你在之前那段实习经历中有没有什么技术性的突破(我只是实习了44天工作28天,我把我能说的都说了)4.你封装的哪个表单组件支不支持动态传值5.自己在实习阶段Vue3项目封装过hook吗6.hook有什么作用7.Vue2和Vue3的响应式区别(我说一个是proxy是拦截所有的底层操作,Object.defineProperty本身就是一个底层操作,有些东西拦截不了,比如数组的一些操作还有等等,面试官就说实在要拦截能不能拦截????我心想肯定不行呀,他的底层机制就不允许吧)8.pinia和vuex的区别(这个回答不出来是我太久没用了)9.pinia和zustand的区别,怎么选(直接给我干懵了)(我说react能用pinia吗&nbsp;&nbsp;他说要用的话也可以)10.渲染一万条数据,怎么解决页面卡顿问题(我说分页、监听滚轮动态加载,纯数据展示好像还可以用canvas画)(估计是没说虚拟表单,感觉不满意)11.type和interface的区别12.ts的泛型有哪些作用(我就说了一个结构相同但是类型不同的时候可以用,比如请求响应的接口,每次的data不同,这里能用一个泛型,他问我还有什么)13.你项目用的是React,如果让你再写一遍你会选择什么14.pnpm、npm、yarn的区别15.dependencies和devdependencies的区别总而言之太久没面试了,上一段实习的面试js问了很多。结果这次js一点没问,网络方面也没考,表现得很一般,但是知道自己的问题了&nbsp;&nbsp;好好准备,等待明天的影石360和周四的腾讯了&nbsp;&nbsp;加油!!!
解zj:大三的第一段面试居然是这样的结局
查看15道真题和解析
点赞 评论 收藏
分享
11-07 03:09
深圳大学 C++
实习秋招做的很差,也想总结一下自己的大学生涯吧。不算太摆,但是很迷。0.大学前高考发挥超常,才来到深大计软。大学前暑期基本上都是玩游戏了。接触了python(李笑来)但是没接触到online&nbsp;judge,也没去多了解编程生态、计算机行业。背了背单词,但是没去规划指标如六级,没制定计划不了了之。1.大一军训时去了校ACM培训,当时dev编译器都不会下载。军训期间积极看B站大学c语言课程。力扣,牛客都是知道的,但是没有成为很好的跳板。第二次培训,看不懂cpp的&nbsp;cin&amp;gt;&amp;gt;,网上搜了也没搞懂,再加上周末跟训得三个多小时,感觉跟不上放弃了。自费报了蓝桥杯,混了省二跟着一些机构课程学习,走的cpp路线。暑假在linux上熟悉vim操作。2.大二朝花夕拾,又去参加ACM训练,跟了一年,寒假都在码&nbsp;带懒标记的线段树。codeforce和力扣赛都在打打(竞赛还是有趣的)。集训队入队周赛打四场,校赛拿金,面试时表现差,说自己想就业,遂挂。当时四月多,2024华为软件精英挑战赛也在打,拿了80名(前64才有三等奖)。蓝桥杯国二。很多晚上跑步来消磨时间。3.大三上修了深大最强的计算机图形学,408找实习,投简历了说自己只有周末有空,遂没在找。也没看牛客真实行情。寒假随便做了个日志器,属于混过去了。当时接到字节的面试(人生处女面),前一天觉都睡不好,很紧张,手撕做的不好,话都说不利索了。面评脏。大三下找实习,cpp选手,没有很好经历、项目,运气好去了学校附近中厂实习。4.大四现在,貌似对开发不上心?没有好的offer(甚至hot100不会做)其实同届好多同学都拿的不错。还有保研C9的。嗯,考研吧。————对自己行为的分析:a.应试教育+应试家庭教育,我的个性是固执、遵规守矩的。b.还有莫名的孤独,明明有很多朋友,但还是没有很好的内驱力,没有坚定的理想。c.自己没有很好的调研、探索和规划能力。大家也可以锐评一下😊
_Matrice_:差不多的性格,不然不会本科时硬杠cpp(那个时候还没有大模型,啃完一整本primer和习题,还是做不出来什么东西),还找不到方向,相比之下学习一些应用层的同学已经能够参考别人的方法做出实用的应用了。学东西,找实习,感觉更多地是出于和别人比较,而不是自我内驱。不过...正如deft所说,人生不需要他人的建议,所以也没有标准化的路径,在能够自食其力的背景下慢慢找到自己的生活方式吧...。另外面试很多时候看运气、眼缘
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务