最大网络流算法之增广路算法
理论讲解
为了在一个图中得到最大流,可以从任何一个可行流开始,沿着增广路对网络流进行增广,知道图中不存在增广路为止。
如何找增广路:从源点S出发用求最短路的算法根据边的容量 - 流量 找一条最短路 记录下来该路径,走一边该路径,找到该路中(容量-流量的最小值),对该路径上所有边的流量都加上该最小值。
直到找不到图中的增广路,即说明该网路的流量已经达到了最大。
附上代码:
queue<int> q;
int bfs() //找增广路径 用spfa算法
{
int i,t;
while(!q.empty()) q.pop(); //清空队列
memset(path,-1,sizeof(path));
path[start]=0,flow[start]=INF;
q.push(start);
while(!q.empty())
{
t=q.front();
q.pop();
if(t==end) break;
for(i=1; i<=m; i++)
{
if(i!=start && path[i]==-1 && map[t][i])
{
flow[i]=flow[t]<map[t][i]?flow[t]:map[t][i];
q.push(i);
path[i]=t;
}
}
}
if(path[end]==-1) return -1; //没有找到
return flow[m]; //一次遍历之后的流量增量
}
int Edmonds_Karp()
{
int max_flow=0,step,now,pre;
while((step=bfs())!=-1) //找不到增路径时退出
{
max_flow+=step;
now=end;
while(now!=start)
{
pre=path[now];
map[pre][now]-=step; //更新正向边的实际容量
map[now][pre]+=step; //添加反向边
now=pre;
}
}
return max_flow; //返回最大流
}
</pre></p><p><span style="font-size:18px;"> </span></p><p><span style="font-size:18px;"> </span></p><p><span style="font-size:18px;">网络流入门例题 <a target=_blank href="http://poj.org/problem?id=1273"><span style="color:rgb(102, 102, 102);">http://poj.org/problem?id=1273</span></a></span></p><h3><span style="font-size:18px;">题目大意 <u> <a target=_blank href="http://blog.csdn.net/kg_second/article/details/8041768"><span style="color:rgb(73, 73, 73);">每当下雨,农夫</span><span style="color:rgb(73, 73, 73);">住</span><span style="color:rgb(73, 73, 73);">地方周围就变成了一个池塘,这让他很</span><span style="color:rgb(73, 73, 73);">高兴</span><span style="color:rgb(73, 73, 73);">,所以决心要把这个问题解</span></a><a target=_blank href="http://blog.csdn.net/kg_second/article/details/8041768"><span style="color:rgb(73, 73, 73);">决掉,所以他就在四周建造了一些渠沟排水,把这水排到一个小溪处。编号为<span style="font-family:Arial;">1</span><span style="font-family:宋体;">的节点作为池塘,编号为</span><span style="font-family:Arial;">n</span><span style="font-family:宋体;">的地方作为小溪。求最大排水量</span></span></a></u></span></h3><p><span style="font-size:18px;"><span style="color:rgb(73, 73, 73);">注意重边的情况就可以了</span><span style="color:rgb(73, 73, 73);">。</span></span></p><p><span style="font-size:18px;">代码</span></p><p><span style="font-size:18px;"></span><pre name="code" class="cpp">#include <set>
#include <map>
#include <queue>
#include <stack>
#include <math.h>
#include <string>
#include <vector>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <functional>
#define PI acos(-1.0)
#define esp 1e-8
#define MAXN 220
#define mem(a) memset(a,0,sizeof(a));
#define mem_1(a) memset(a,-1,sizeof(a));
using namespace std;
const int INF = 0x7FFFFFFF;
int cap[MAXN][MAXN];
int n,m;
int path[MAXN],flow[MAXN];
int bfs()
{
mem_1(path);
path[1] = 0;
flow[1] = INF;
queue<int> Q;
Q.push(1);
while(!Q.empty())
{
int now = Q.front();
Q.pop();
if(now==m) break;
for(int v = 1;v<=m;v++)
{
if(v!=1 && path[v]==-1 && cap[now][v] )
{
path[v] = now;
Q.push(v);
flow[v] = min(flow[now],cap[now][v]);
}
}
}
if(path[m]==-1) return -1;
return flow[m];
}
int E_K()
{
int xx,pre;
int ans_flow = 0;
while( (xx = bfs())!=-1)
{
ans_flow+=xx;
int now = m;
while(now!=1)
{
pre = path[now];
cap[pre][now]-=xx;
cap[now][pre]+=xx;
now = pre;
}
}
return ans_flow;
}
int main()
{
int tem1,tem2,tem3;
while(cin >> n >> m)
{
mem(cap);
for(int i=1;i<=n;i++)
{
cin >> tem1 >> tem2 >> tem3;
cap[tem1][tem2] +=tem3;
}
cout << E_K() << endl;
}
return 0;
}
暑假集训生活开始了。。