Thorough network flow -wfx- maximum flow

premise:

We imagine the water plant to your home water supply network is a complex directed graph, each tube has a maximum load of water-saving flow. Waterworks do not turn on the water, your home is without water. But even if waterworks desperately to the water pipe network inside your home to receive water flow is the upper limit (after all, the limited carrying capacity of each pipe). You want to know how much water you can get, this is a network flow problem.

Information on the Internet looking for a long time, although a lot of network flow data to explain but easy to understand very little(Perhaps I was too konjac, right), Wrote this article just hope people can learn to spot incoming network flow(Can thumbs up)

First of all

Maximum Flow:

What is the maximum flow is simply water from a source point s through many paths, through a lot of points to reach the Meeting Point t, you can have up to ask how much water can reach the point t.

Understood in conjunction with the illustrated: from s to t via a plurality of points, a plurality of sides, each side of the stream can not exceed the edge weight value (but not more than can be less than or equal), the maximum flow of the diagram is 10 + 22 + 45 = 77. If you still can not understand, we'll put it another way, assuming that s t want to go to the city have personal inf city, but from s to t to go through to get to some cities, the city of 3 tickets (more than figure as an example) where s to left 10, 3 to 15 t of tickets left, so the other way, eventually up to ask how many people can reach t City?

 

A:

 

Edmond—Karp

Augmenting path:

Augmenting path: augmenting path means a path from s to t, the flow through this route, such that the current flows (t person can be reached) can be increased. So seeking maximum flow problem can be converted to solving problems constantly augmenting path, and, obviously, when the figure augmenting path does not exist reaches the maximum flow. Specifically how does it work? Is very simple, can be found directly from the broad s to t, s from the wide search began outwardly by the edge weight value greater than 0 (because the back edge weight value will be reduced, so that there may be the right side of the edge 0), until you find t, and then locate the path to the upper right side of the smallest, denoted mi, then the maximum flow plus mi, then the right side of each edge on the path minus mi, until it can not find an augmenting path ( ) up to the path from s to t. (Mi Why use it? You have to fight more and more people go on this way, but can not make people stop in a city)

 

Code:

#include<cstdio>
#include<cstdlib>
#include<queue>
#include<iostream>
using namespace std;
const int inf = 2147483647;
const int MAXN = 100100;
int head[MAXN],cnt = 1,low[MAXN],pre[MAXN],n,m,S,T;
int maxflow;
bool v[MAXN];
inline int read(){
	int res = 0; char ch = getchar(); bool bo = false;
	while(ch < '0' || ch > '9') bo = (ch == '-'), ch = getchar();
	while(ch >= '0' && ch <= '9') res = (res << 1) + (res << 3) + (ch ^ 48), ch = getchar();
	return bo ? -res : res;
}
struct node{int nxt,to,dis;}e[MAXN<<1];
void add(int from,int to,int dis)
{
	e[++cnt]= (node){head[from],to,dis};
	head[from]=cnt;
}
void EK()
{
	int x=T;
	while(x!=S)
	{
		int i=pre[x];
		e[i].dis-=low[T];
		e[i^1].dis+=low[T];
		x=e[i^1].to;
	}
	maxflow += low[T];
}
queue <int> q;
bool bfs()
{
	for(int i=1;i<=n;i++)v[i]=0;
	while(q.size()) q.pop();
	v[S]=1;
	q.push(S);
	low[S]=inf;
	while(q.size())
	{
		int x=q.front();
		q.pop();
		for(int i=head[x];i;i=e[i].nxt)
		{
			if(e[i].dis > 0)
			{
				int y=e[i].to;
				if(v[y])continue;
				low[y]=min(low[x],e[i].dis);
				pre[y]=i;
				q.push(y);v[y]=1;
				if(y==T)return true;
			}
		}
	}
	return false;
}
int main()
{
	n=read();m=read();S=read();T=read();
	int x,y,c;
	for(int i=1;i<=m;i++)
	{
		x=read();y=read();c=read();
		add(x,y,c); add(y,x,0);
	}
	while(bfs()) EK();
	printf("%d\n",maxflow);
	return 0;
}

  

Dinic:

 

Dinic algorithm is divided into two steps:

 

  1. bfs stratification (in the bfs EK is looking for augmenting paths)
  2. dfs augmented(Dfs? EK looks like there is in this stuff, ah, OK efficiently?)
  3. what! Just two steps do not say?Repeat 1.2 until no augmenting path map

 

What does that mean?

And EK, we still have to determine the figure by bfs whether there are augmenting path, but DInic algorithm in the bfs slightly different, this time, we do not record the path, but to every point of stratification, for any point i, i from s to each through a multi-point, let a large number of layers.

In fact, each time only to find the number of layers of freshman that find the shortest augmenting path, it is mythical:

With stratification, we would not choose s-> 1-> 2-> 4-> 5-> 3-> t a

Just I said, the next step is to divide finish layer dfs augmentation.

In Dinic, we find an augmenting path is a deep search:

Code:

 

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int N = 100100;
const int inf = 214748347;
int cnt=1,head[10010],d[10010],n,m,s,t,maxflow;
bool v[N];
struct node{int nxt,to,dis;}e[N<<1];
void add(int from,int to,int dis)
{
	e[++cnt] = (node){head[from],to,dis};
	head[from]=cnt;
}

queue <int> q;
bool bfs()
{
	memset(d,0,sizeof d);
	while(q.size())q.pop();
	q.push(s);
	d[s]=1;
	while(q.size())
	{
		int x=q.front();q.pop();
		for(int i=head[x];i;i=e[i].nxt)
		{
			int y=e[i].to;
			if(e[i].dis && !d[y])
			{
				q.push(y);
				d[y]=d[x]+1;
				if(e[i].to==t)return 1;
			}
		}
	}
	return 0;
}
int dinic(int x,int flow)
{
	if(x==t)return flow;
	int rest=flow,k;
	for(int i=head[x];i&&rest;i=e[i].nxt)
	{
		int y=e[i].to;
		if(e[i].dis&&d[y]==d[x]+1)
		{
			k=dinic(y,min(rest,e[i].dis));
			if(!k) d[y]=0;
			e[i].dis-=k;
			e[i^1].dis+=k;
			rest-=k;
		}
	}
	return flow-rest;
}
int main()
{
	scanf("%d%d%d%d",&n,&m,&s,&t);
	int x,y,c;
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&x,&y,&c);
		add(x,y,c);add(y,x,0);
	}
	int flow=0;
	while(bfs())
	{
		while(flow=dinic(s,inf)) maxflow+=flow;
	}
	printf("%d\n",maxflow);
	return 0;
}

 

  

 

还有一种超强的优化:当前弧(边)优化:

我们定义一个数组cur记录当前边(弧)(功能类比邻接表中的head数组,只是会随着dfs的进行而修改),

每次我们找过某条边(弧)时,修改cur数组,改成该边(弧)的编号,

那么下次到达该点时,会直接从cur对应的边开始(也就是说从head到cur中间的那一些边(弧)我们就不走了)。

有点抽象啊,感觉并不能加快,然而实际上确实快了很多。

代码:

bool bfs()
{
	for(int i=1;i<=n;i++)
	{
		cur[i]=head[i];///////////////////只修改这几处,让你的代码飞快,相当于节省了dfs
          d[i]=0;///////中的链式前向星,因为head【】的边有的已经在前面使用 } while(q.size())q.pop(); q.push(s); d[s]=1; while(q.size()) { int x=q.front();q.pop(); for(int i=head[x];i;i=e[i].nxt) { int y=e[i].to; if(e[i].dis && !d[y]) { q.push(y); d[y]=d[x]+1; if(e[i].to==t)return 1; } } } return 0; } int dinic(int x,int flow) { if(x==t)return flow; int rest=flow,k; for(int i=cur[x];i&&rest;i=e[i].nxt)////////////////// { cur[x]=i;///////////////// int y=e[i].to; if(e[i].dis&&d[y]==d[x]+1) { k=dinic(y,min(rest,e[i].dis)); if(!k) d[y]=0; e[i].dis-=k; e[i^1].dis+=k; rest-=k; } } return flow-rest; }

  

感谢__wfx 一下午的讲解,自己明白了很多

 

 

!!!!!!!!!!!!!!!!!!

缘来是你

 

Guess you like

Origin www.cnblogs.com/yelir/p/11520216.html