网络流入门

Posted uid001

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络流入门相关的知识,希望对你有一定的参考价值。

求最大流一般采用Ford-Fulkerson算法, 即每次从残量网络中任选一条增广路来增广, 直到没有增广路为止.

FF算法最坏复杂度是$O(E|f^*|)$, FF算法的一个优化是EK算法, 每次用bfs选择一条最短的增广路来增广, 可以证明复杂度是$O(VE^2)$, 代码如下

int n, m, s, t;
struct _ {int from,to,w;};
vector<_> E;
vector<int> g[N];
int a[N], pre[N];

void add(int x, int y, int w) {
	g[x].pb(E.size());
	E.pb({x,y,w});
}

int Maxflow(int s, int t) {
	int ans = 0;
	for (; ; ) {
		REP(i,1,n) a[i] = 0;
		queue<int> q;
		q.push(s);
		a[s] = INF;
		while (!q.empty()) {
			int x = q.front();q.pop();
			for (auto &t:g[x]) {
				auto &e = E[t];
				if (!a[e.to]&&e.w>0) {
					pre[e.to] = t;
					a[e.to] = min(a[x], e.w);
					q.push(e.to);
				}
			}
			if (a[t]) break;
		}
		if (!a[t]) break;
		for (int u=t; u!=s; u=E[pre[u]].from) {
			E[pre[u]].w -= a[t];
			E[pre[u]^1].w += a[t];
		}
		ans += a[t];
	}
	return ans;
}

int main() {
	scanf("%d%d%d%d", &n, &m, &s, &t);
	REP(i,1,m) {
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		add(u,v,w),add(v,u,0);
	}
	printf("%d\n", Maxflow(s,t));
}

最小费用最大流问题, 每个边上通过单位流量有一定费用, 将bfs改为spfa即可, 复杂度$O(V^2E^2)$, 也可以用dijkstra优化, 复杂度$O(VE(E+VlogV))$ 

const int N = 3e5+10;
int n, m, s, t;
struct _ {int from,to,w,f;};
vector<_> E;
vector<int> g[N];
int a[N], pre[N], inq[N], d[N];
int max_flow, min_cost;

void add(int x, int y, int w, int f) {
	g[x].pb(E.size());
	E.pb({x,y,w,f});
}

queue<int> q;
void MaxflowMincost(int s, int t) {
	for (; ; ) {
		REP(i,0,n) a[i]=d[i]=INF,inq[i]=0;
		while (q.size()) q.pop();
		q.push(s);
		a[s] = INF, d[s] = 0;
		while (!q.empty()) {
			int x = q.front();q.pop();
			inq[x] = 0;
			for (auto &t:g[x]) {
				auto &e = E[t];
				if (e.w>0&&d[e.to]>d[x]+e.f) {
					d[e.to]=d[x]+e.f;
					pre[e.to] = t;
					a[e.to] = min(a[x], e.w);
					if (!inq[e.to]) {
						inq[e.to]=1;
						q.push(e.to);
					}
				}
			}
		}
		if (a[t]==INF) break;
		for (int u=t; u!=s; u=E[pre[u]].from) {
			E[pre[u]].w -= a[t];
			E[pre[u]^1].w += a[t];
		}
		max_flow += a[t];
		min_cost += a[t]*d[t];
	}
}

int main() {
	scanf("%d%d%d%d", &n, &m, &s, &t);
	REP(i,1,m) {
		int u, v, w, f;
		scanf("%d%d%d%d", &u, &v, &w, &f);
		add(u,v,w,f),add(v,u,0,-f);
	}
	MaxflowMincost(s,t);
	printf("%d %d\n", max_flow, min_cost);
}

 

以上是关于网络流入门的主要内容,如果未能解决你的问题,请参考以下文章

网络流最大流入门(Dinic算法)模板

Tile Cut~网络流入门题

网络最大流入门

网络流入门 Drainage Ditches

POJ-1273 Drainage Ditches (网络流入门题)

转一些图论网络流入门题总结汇总