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

网络流模板

作者:互联网

网络流

没有详细的分析解释,只有两个模板,若要学习网络流知识,还请前往它站

网络\(G = (E , V)\)是一张有向图,其中每条边都有一个流量c,还有两个特殊点S(源点),T(汇点)。设\(f(x,y)\)为定义在节点二元组\((x,y\in V)\)的流函数,满足

  1. 容量限制 f(x,y) <= c(x,y)
  2. 斜对称 f(x,y) + f(y,x) = 0
  3. 流量守恒 \(\forall u \neq S , T. \ \ \sum_{(u,x)\in E}f(u,x) = \sum_{(x,v) \in E} f(x,v)\)

\(\sum_{(S,x)\in E}f(S,x)\) 称为全图的流量

EK

增广路指从S到T的一条剩余容量不为零的路径

求最大流的过程就是不断求增广路的过程。

EK算法就是不断bfs求增广路然后修改剩余容量

复杂度\(O(nm^2)\)实际跑不满,可以处理\(1e3 \thicksim 1e4\)的数据

#include<iostream>
#include<queue>
using namespace std;
const int N = 205 , M = 5005 , inf = 214748647;
int n , m , S , T , Cnt = 1;
int head[N] , f[N] , pre[N] , vis[N];

long long Answer;

struct edge{ int v , c , nex; }e[M << 1];
inline void add(int u , int v , int c)
{
	e[++Cnt].v = v; e[Cnt].c = c; e[Cnt].nex = head[u]; head[u] = Cnt;
}

bool Bfs()
{
	queue<int> q;
	for(int i = 1 ; i <= n ; ++i) vis[i] = 0;
	f[S] = inf; vis[S] = 1; q.push(S);
	while(q.size())
	{
		int x = q.front(); q.pop();
		if(x == T) return true;
		for(int i = head[x] ; i ; i = e[i].nex) if(e[i].c && !vis[e[i].v])
		{
			f[e[i].v] = min(f[x] , e[i].c);
			pre[e[i].v] = i; vis[e[i].v] = 1; q.push(e[i].v);
		}
	}
	return false;
}

void Update()
{
	int x = T , i;
	Answer += f[T];
	while(x != S)
	{
		i = pre[x];
		e[i].c -= f[T]; e[i^1].c += f[T];
		x = e[i^1].v;
	}
}

int main()
{
	int u , v , c;
	cin >> n >> m >> S >> T;
	for(int i = 1 ; i <= m ; ++i)
	{	
		cin >> u >> v >> c;
		add(u , v , c);
		add(v , u , 0);
	}
	while(Bfs()) Update();
	cout << Answer << '\n';
	return 0;
}

Dinic

残量网络: 由剩余容量大于0的边构成的网络

分层图: d[x]表示从S到x的长度

算法,先bfs构造分层图,然后在分层图上dfs,回溯是更新流量

#include<iostream>
#include<queue>
using namespace std;
const int N = 205 , M = 5005 , inf = 214748647;
int n , m , S , T , Cnt = 1;
int head[N] , cur[N] , d[N];

long long Answer;

struct edge{ int v , c , nex; }e[M << 1];
inline void add(int u , int v , int c)
{
	e[++Cnt].v = v; e[Cnt].c = c; e[Cnt].nex = head[u]; head[u] = Cnt;
}
queue<int> q;
bool Bfs()
{
	for(int i = 1 ; i <= n ; ++i) d[i] = 0;
	q.push(S); d[S] = 1;
	while(q.size())
	{
		int x = q.front(); q.pop();
		for(int i = head[x] ; i ; i = e[i].nex) if(e[i].c && !d[e[i].v])
		{
			d[e[i].v] = d[x] + 1; q.push(e[i].v);
		}
	}
	return d[T];
}

long long Dfs(int x , int flow)
{
	if(x == T || flow == 0) return flow;
	long long res = 0;
	for(int &i = cur[x] ; i ; i = e[i].nex)
	{
		int v = e[i].v;
		if(e[i].c && d[v] == d[x] + 1)
		{
			long long k = Dfs(v , min(e[i].c , flow));
			if(k)
			{
				flow -= k; res += k; e[i].c -= k; e[i^1].c += k;
				if(!flow) return res;
			}
		}
	}
	return res;
}

int main()
{
	int u , v , c;
	cin >> n >> m >> S >> T;
	for(int i = 1 ; i <= m ; ++i)
	{	
		cin >> u >> v >> c;
		add(u , v , c);
		add(v , u , 0);
	}
	long long tmp;
	while(Bfs()) 
	{
		for(int i = 1 ; i <= n ; ++i) cur[i] = head[i];
		while(tmp = Dfs(S , inf)) Answer += tmp;
	}
	cout << Answer << '\n';
	return 0;
}

标签:int,网络,long,Bfs,add,include,模板
来源: https://www.cnblogs.com/R-Q-R-Q/p/16435949.html