数据输入格式:首先输入顶点个数n和弧数m,然后输入每条弧的数据。规定源点为顶点0,汇点为顶点n-1.每条弧的数据格式为:u,v,w,分别表示这条弧的起点,终点,容量。顶点序号从0开始。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define maxn 1005
#define MAXN 2005
#define mod 1000000009
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
typedef long long ll;
using namespace std;
int d[maxn]; //标号
int mp[maxn][maxn]; //残留网络,初始为原图
int num[maxn]; //num[i]表示标号为i的顶点数有多少
int pre[maxn]; //记录前驱
int n,m,s,t; //n个顶点,m条边,源点s,汇点t
void init() //bfs计算标号,汇点t的标号为零
{
int k;
queue<int>Q;
memset(d,INF,sizeof(d)); //初始化d数组为无穷大
memset(num,0,sizeof(num)); //初始化num数组num
Q.push(t); //汇点t入队列
d[t]=0; //汇点标号为零
num[0]=1; //标号为0的顶点数为1
while (!Q.empty())
{
k=Q.front();
Q.pop();
for (int i=0;i<n;i++)
{
if (d[i]>=n&&mp[i][k]>0)
{
d[i]=d[k]+1;
Q.push(i);
num[d[i]]++;
}
}
}
}
int findAlowArc(int i) //从i出发寻找允许弧
{
int j;
for (j=0;j<n;j++)
if (mp[i][j]>0&&d[i]==d[j]+1)
return j;
return -1;
}
int reLable(int i) //重新标号
{
int mm=INF;
for (int j=0;j<n;j++)
if (mp[i][j]>0)
mm=min(mm,d[j]+1);
return mm==INF?n:mm;
}
int maxFlow(int s,int t) //求从源点s出发的最大流
{
int flow=0,i=s,j;
int delta; //增量
memset(pre,-1,sizeof(pre));
while (d[s]<n)
{
j=findAlowArc(i);
if (j>=0)
{
pre[j]=i;
i=j;
if (i==t) //更新残留网络
{
delta=INF;
for (i=t;i!=s;i=pre[i])
delta=min(delta,mp[pre[i]][i]);
for (i=t;i!=s;i=pre[i])
mp[pre[i]][i]-=delta,mp[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;
}
int main()
{
int u,v,c; //弧的起点,终点,容量
while (scanf("%d%d",&n,&m)!=EOF) //读入顶点个数n和弧数m
{
memset(mp,0,sizeof(mp));
for (int i=0;i<m;i++)
{
scanf("%d%d%d",&u,&v,&c);
mp[u][v]=c;
}
s=0,t=n-1;
init();
printf("%d\n",maxFlow(0,n-1));
}
return 0;
}
/*
6 10
0 1 8
0 2 4
1 3 2
1 4 2
2 1 4
2 3 1
2 4 4
3 4 6
3 5 9
4 5 7
*/