最大流ISAP(距离标号最短增广路算法)模板
#include <iostream>
#include <queue>
#define msize 1024 //最大顶点数目
using namespace std;
int d[msize]; //标号
int r[msize][msize]; //残留网络,初始为原图
int num[msize]; //num[i]表示标号为i的顶点数有多少
int pre[msize]; //记录前驱
int n,m,s,t; //m个顶点,n条边,从源点s到汇点t
//此处别忘了在使用最大流之前先调用此函数初始化标号
void ini_d() //BFS计算标号,汇点t标号为0
{
int k;
queue<int>Q;
memset(d,1,sizeof(d)); //将距离设置成为无穷大,此处亦可以使用for循环实现
memset(num,0,sizeof(num));
Q.push(t);
d[t]=0; //汇点的标号为0
num[0]=1;
while (!Q.empty())
{
k=Q.front(),Q.pop();
for (int i=0;i<m;i++) //遍历所有的结点
{
if (d[i]>=m&&r[i][k]>0) //此处要特别注意,通过frontint的值改变其他的距离标号
{
d[i]=d[k]+1;
Q.push(i);
num[d[i]]++;
}
}
}
}
int findAlowArc(int i) //从i出发寻找允许弧
{
int j;
for (j=0;j<m;j++) if (r[i][j]>0&&d[i]==d[j]+1) return j;
return -1;
}
int reLable(int i) //重新标号
{
int mm=INT_MAX;
for (int j=0;j<m;j++)
if (r[i][j]>0) mm=min(mm,d[j]+1);
return mm==INT_MAX?m:mm;
}
int maxFlow(int s,int t) //从源点s出发的最大流
{
int flow=0,i=s,j;
int delta; //增量
memset(pre,-1,sizeof(pre));
while (d[s]<m)
{
j=findAlowArc(i);
if (j>=0)
{
pre[j]=i;
i=j; //从前往后找
if (i==t) //更新残留网络
{
delta=INT_MAX;
for (i=t;i!=s;i=pre[i]) delta=min(delta,r[pre[i]][i]); //找到增广路径的增量
for (i=t;i!=s;i=pre[i]) r[pre[i]][i] -= delta, r[i][pre[i]] += delta; //更改流量
flow += delta;
}
}
else
{
int x=reLable(i); //重新标号
num[x]++;
num[d[i]]--;
if (num[d[i]]==0) return flow; //间隙优化
d[i]=x;
if (i!=s) i=pre[i];
}
}
return flow;
}