预流推进算法(压入与重标记方法):
预流推进算法将网络从源点到汇点至于从上到下的高度中。在算法执行过程中,每个节点的存留量(入流-出流)>=0,当一个点的存留量大于零时,则称此结点为活结点。算法从源点开始向下推流,通过不断地寻找活结点,将流量推向以该点为起点的可推流边(可推流边指与该点相连且高度比该点小1的边),该过程即为压入。如果在该点处找不到可推流边,则将该点的高度加1,以实现将过大的流向后推进,该过程称为重标记。因此,在预流推进算法的一次迭代中,要么执行压入操作,要么执行重标记操作。
综上,预流推进算法的框架:
1)、构造初始流。将源点高度标记为n,其余点高度均为0;
2)、如果残留网络中不存在活结点,则算法结束。否则继续执行下一步;
3)、选取活结点,如果该结点出边为可推流边,则沿此边推流,否则将该节点高度加1,执行步骤2)。
g[][]为每边的容量,c[]为每个点的存留量,h[]为每个顶点的高度,sum为最大流。
则预流推进算法代码如下:
void maxflow(int s,int e)
{
memset(c,0,sizeof(c));
c[s]=MAXINT;
c[e]=-MAXINT;
memset(h,0,sizeof(h));
h[s]=n;
sum=0;
queue<int> que; //活顶点队列
que.push(s);
while(!que.empty())
{
int u=que.front();
que.pop();
for (int i=0;i<n;i++)
if (u==s||h[u]==h[i]+1)
{
push(u,i,e);
if (i!=s&&i!=e) que.push(i);
}
if (u!=s&&u!=e&&c[u]>0)
{
relabel(u);
que.push(u);
}
}
}
void push(int u,int v,int e)
{
int min=c[u]<g[u][v]? c[u] : g[u][v];
if (v==e) sum+=min;
g[u][v]-=min;
g[v][u]=+min;
c[u]-=min;
c[v]+=min;
}
void relabel(int u)
{
h[u]++;
}