网络流之最大流Ford-Fulkerson算法

最大流问题可以利用Ford-Fulkerson算法进行求解,其中Ford-Fulkerson算法求解步骤就是:构建出残余网络图,在残余网络图中寻找增广路径,利用增广路径中最小flow进行更新残余网络图,再寻找增广路径,以此往复,直到在残余网络图中找不到增广路径为止,这时候的totalflow就是整个网络图中的最大流。

#include"stdafx.h"
#include
#include
#include
#include
#include
using namespace std;
const int maxn = 1e5;
const int INF = 1e9;
struct node {
	int v;
	int volume;//容量
	int flow;//剩余流入量
};
vector adj[maxn];//邻接表存储图
int vertexnum, edgenum;//顶点数、边数
bool vis[maxn] = { false };//
int minflow[maxn] = { 0 };//minflow[i]=k表示从s到达i这条增广路径中的最小flow为k
vector path[maxn];//path[i]记录了从s到达结点i的增广路径序列
int bfs(int s, int t) {//广度优先bfs寻找增广路径
	queueq;
	minflow[s] = INF;//
	path[s].push_back(s);
	q.push(s);
	vis[s] = true;//标记顶点s已入队或者已被访问
	bool flag = false;//标志是否有从s到t的增广路径
	while (!q.empty()) {
		int u = q.front();
		q.pop();
		for (int i = 0; i < adj[u].size(); i++) {
			int v = adj[u][i].v;
			int flow = adj[u][i].flow;
			if (vis[v] == false && flow>0) {//如果v未被访问且flow大于0
				q.push(v);
				vis[v] = true;
				//更新到达v的路径【从s到达v的增广路径为:s到达u的路径再加上从u到达v的路径】
				path[v] = path[u];
				path[v].push_back(v);//将结点v加入到路径中
				//
				minflow[v] = min(minflow[u], flow);//更新增广路径上的最小流
				if (v == t) {
					while (!q.empty()) q.pop();//清空队列中的元素
					flag = true;//标志有从s到t的增广路径
					break;
				}
			}
		}
	}
	if (flag == true) return minflow[t];//返回增广路径上的最小flow
	else return -1;//如果没找到从s到t的增广路径,则返回-1
}
void updatenetflow(int k,vector path) {//更新残余网络
	int u = path.front();
	for (int i = 1; i < path.size(); i++) {
		int v = path[i];
		for (int j = 0; j < adj[u].size(); j++) {
			if (adj[u][j].v == v) {
				adj[u][j].flow -= k;
				break;
			}
		}
		for (int j = 0; j < adj[v].size(); j++) {
			if (adj[v][j].v == u) {
				adj[v][j].flow += k;
				break;
			}
		}
		u = v;
	}
}
int Ford_Fullkerson(int s, int t) {//最大流算法
	int totalflow = 0;//从s到达t的最大网络流
	int flow;
	do {
		for (int i = 0; i < vertexnum; i++) {//bfs之前将以下数据全部清空
			while (!path[i].empty()) path[i].pop_back();
			minflow[i] = 0;
			vis[i] = false;
		}
		flow = bfs(s, t);//bfs进行寻找增广路径,并return增广路径中最小flow
		if (flow != -1) {//如果找到增广路径
			totalflow += flow;
			updatenetflow(flow, path[t]);//更新残余网络
		}
	} while (flow != -1);
	return totalflow;
}
int main() {
	cin >> vertexnum >> edgenum;
	int vertex1, vertex2, volume;
	for (int i = 0; i < edgenum; i++) {
		cin >> vertex1 >> vertex2 >> volume;//结点1,结点2,以及结点1到达结点2的传输的最大数据量
		node N;
		N.v = vertex2;
		N.volume = volume;
		N.flow = volume;
		adj[vertex1].push_back(N);
		N.v = vertex1;
		N.flow = 0;
		adj[vertex2].push_back(N);
	}
	int s, t;
	cin >> s >> t;
	cout << Ford_Fullkerson(s, t);
	return 0;
}
---------------------------------------------------------------------------------------
bool dfs(int s, int t) {//深度优先遍历图寻找增广路径
	if (s == t) {
		path.push_back(s);//path数组中保存了从s到t的增广路径序列
		return true;//找到从s到达t的增广路径,返回true
	}
	vis[s] = true;
	path.push_back(s);
	for (int i = 0; i < adj[s].size(); i++) {
		int v = adj[s][i].v;
		int flow = adj[s][i].flow;
		if (vis[v] == false && flow>0) {
			if (flow < miniflow) {
				miniflow = flow;
			}
			bool flag = dfs(v, t);
			if (flag == true) return true;//如果找到增广路径,则return返回,不需要再进行递归了
		}
	}
	//回溯
	vis[s] = false;
	path.pop_back();
	return false;//如果没找到,则return false
}

 

你可能感兴趣的:(经典图论算法,最大流)