现在的位置: 首页 > 综合 > 正文

最大流算法

2018年02月11日 ⁄ 综合 ⁄ 共 1628字 ⁄ 字号 评论关闭

基本的知识,解决什么问题这些东西就不说啦。算法导论和很多大神博客都讲解的很详细。

它其实就是不停的找增广路直到找不到为止。此时通过的所有流量就是最大流量。

我推荐一篇文章:(基本过程讲解的很详细,我很收益。)

Ford-Fulkerson 最大流算法

下面是我的实现。

参考了 最大流Ford-Fulkerson的算法实现

#include<iostream>
#include<queue>
using namespace std;
#define MAX 1024
int nodes,edges;

int capacity[MAX][MAX];//记录边的当前还可以通过的最大流量
int maxflow=0;
bool isVisited[MAX];//在BFS或DFS找增广路的时候记录该元素是否访问过
int pre[MAX];//记录节点的前一个节点

/*
	我最疑惑的地方是capacity[i][pre[i]]+=increase;这个地方。
	我们一开始以为这只是一个简单的有向图,其实不是,这个有向图会根据它的两个节点之间的通过的流量自动改变
		我们可以把它看成是最原始的有向图中有箭头的两个节点可以相互通过流,而不仅仅是沿箭头的方向通过流(通过判断两个节点之间的最大
		流量来判断。)

	表达能力实在有限。。我自己都觉得没说清楚..
*/
inline int min(int a,int b)
{
	return a>b?b:a;
}

bool DFS(int src)
{
	if(!src)
		pre[src]=-1;
	if(src==nodes-1)
		return true;
	isVisited[src]=true;
	for(int i=0;i<nodes;i++)
	{
		if(!isVisited[i]&&capacity[src][i])
		{
			isVisited[i]=true;
			pre[i]=src;
			if(DFS(i))
				return true;
		}
	}
	return false;
}

bool BFS()
{
	queue<int> myQueue;
	myQueue.push(0);
	isVisited[0]=true;
	pre[0]=-1;
	while(!myQueue.empty())
	{
		int current=myQueue.front();
		myQueue.pop();
		for(int i=0;i<nodes;i++)
		{
			if(!isVisited[i]&&capacity[current][i])
			{
				myQueue.push(i);
				pre[i]=current;
				isVisited[i]=true;
			}
		}
	}
	
	return isVisited[nodes-1];
}

void MaxFlow()
{
	while(1)
	{
		memset(isVisited,false,nodes);
		memset(pre,0xff,4*nodes);
		
	//	if(!DFS(0))
	//		break;
		if(!BFS())
			break;
		
		int increase=MAX;
		int i;
		for(i=nodes-1;pre[i]>=0;i=pre[i])
		{	
			increase=min(increase,capacity[pre[i]][i]);
		}
		for(i=nodes-1;pre[i]>=0;i=pre[i])
		{	
			capacity[pre[i]][i]-=increase;
			capacity[i][pre[i]]+=increase;
		}
		maxflow+=increase;
		

	}
}
void main()
{
	while(1)
	{
		cin>>nodes>>edges;
		int firstnode,secondenode,capa;
		for(int i=0;i<edges;i++)
		{
			cin>>firstnode>>secondenode>>capa;
			capacity[firstnode][secondenode]=capa;
		}
		MaxFlow();
		cout<<maxflow<<endl;
		maxflow=0;

	}
	
}


这里提供两种找增广路的算法:DFS和BFS。

抱歉!评论已关闭.