https://www.cnblogs.com/wally/archive/2013/05/03/3054778.html
邻接矩阵
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 202
#define INF 0x3f3f3f3f
int e[N][N];
int pre[N]; //记录当前点的前驱。
int d[N]; //记录距离标号 i-t距离的下界。
int num[N]; //gap优化,每个距离下标下的节点编号有多少个,为0的话,说明s-t不连通
int SAP(int s,int t){
memset(pre,-1,sizeof(pre));
memset(d,0,sizeof(d));
memset(num,0,sizeof(num));
num[0]=t;
int v,u=pre[s]=s,flow=0,aug=INF;
while(d[s]<t){ //else 残量网络中不存在s-t路。
//寻找可行弧
for(v=1;v<=t;v++){
if(e[u][v]>0&&d[u]==d[v]+1){
break;
}
}
if(v<=t){
pre[v]=u;
u=v;
if(v==t){
aug=INF;
//寻找当前找到路径上的最大流
for(int i=v;i!=s;i=pre[i]){
if(aug>e[pre[i]][i]) aug=e[pre[i]][i];
}
flow+=aug;
//更新残留网络。
for(int i=v;i!=s;i=pre[i]){
e[pre[i]][i]-=aug;
e[i][pre[i]]+=aug;
}
u=s; //从源点开始继续搜。
}
}else{
//找不到可行弧
int minlevel=t;
//寻找与当前点连接的最小的距离标号。
for(v=1;v<=t;v++){
if(e[u][v]>0&&minlevel>d[v]){
minlevel=d[v];
}
}
num[d[u]]--; //当前标号的数目减一
if(!num[d[u]]) break; //出现断层。
d[u]=minlevel+1;
num[d[u]]++;
u=pre[u];
}
}
return flow;
}
int main()
{
int n,m,u,v,w; //m,边数,n,节点数.
while(~scanf("%d%d",&m,&n)){
memset(e,0,sizeof(e));
while(m--){
scanf("%d%d%d",&u,&v,&w);
e[u][v]+=w;
}
printf("%d\n",SAP(1,n));
}
return 0;
}
邻接表
#include <iostream>
#include <string.h>
#include <queue>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAX_N=205; //顶点数上限
const int MAX_M=10000; //总的边数上限
struct edge{
int v,c,next; //v指另一个顶点,c表示容量。
}e[MAX_M];
int p[MAX_N],eid;
void init(){
memset(p,-1,sizeof(p));
eid=0;
}
void insert(int u,int v,int c){ //插入一条从u向v,容量为c的弧。
e[eid].v=v;
e[eid].next=p[u];
e[eid].c=c;
p[u]=eid++;
}
void addedge(int u,int v,int c){ //用insert插入网络中的弧
insert(u,v,c);
insert(v,u,0); //插入一条反方向,当前容量为0的弧
}
int num[MAX_N];
int d[MAX_N];
int cur[MAX_N];
int pre[MAX_N];
int SPA(int s,int t,int n){ //S是源点,T是汇点。
int cur_flow,flow_ans=0,u,tmp,neck,i;
memset(num,0,sizeof(num));
memset(d,0,sizeof(d));
memset(pre,-1,sizeof(pre));
for(i=1;i<=n;i++){
cur[i]=p[i];
}
num[0]=n;
u=s;
while(d[s]<n){
if(u==t){
cur_flow=INF;
for(i=s;i!=t;i=e[cur[i]].v){
if(cur_flow>e[cur[i]].c){ //增广成功,寻找瓶颈边
neck=i;
cur_flow=e[cur[i]].c;
}
}
for(i=s;i!=t;i=e[cur[i]].v){
tmp=cur[i];
e[tmp].c-=cur_flow;
e[tmp^1].c+=cur_flow;
}
flow_ans+=cur_flow;
u=neck; //下次增广从瓶颈边开始
}
//寻找可行弧
for(i=cur[u];i!=-1;i=e[i].next){
if(e[i].c&&d[u]==d[e[i].v]+1) break;
}
if(i!=-1){
cur[u]=i;
pre[e[i].v]=u;
u=e[i].v;
}else{
if(0==--num[d[u]]) break;
cur[u]=p[u];
for(tmp=n,i=p[u];i!=-1;i=e[i].next){
if(e[i].c){
tmp=min(tmp,d[e[i].v]);
}
}
d[u]=tmp+1;
num[d[u]]++;
if(u!=s) u=pre[u];
}
}
return flow_ans;
}
int main() {
int n,m;
while(cin>>m>>n){
init();
for(int i=0;i<m;i++){
int u,v,flow;
cin>>u>>v>>flow;
addedge(u,v,flow);
}
cout<<SPA(1,n,n)<<endl;
}
return 0;
}