#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
#define MM(a,b) memset(a,b,sizeof(a));
typedef unsigned long long u64;
typedef long long lld;
#define maxn 210
const int maxint= 2100000000;
int S,T,g[maxn][maxn];
int pre[maxn]; //前驱;
int lay[maxn]; //层次图;lay[v]表示v到汇点T的最短边数;
int que[maxn];
int gap[maxn];
void up_min(int &x,int y){if(x>y)x=y;}
// bfs求层次图;
void bfs_init(int n){
MM(lay,-1); // 初始化为 -1;
int head=0, tail=0;
que[tail++]= T;
lay[T]=0;
MM(gap,0); // 初始化gap[]: 0;
while(head<tail){
int u= que[head++];
for(int v=1;v<=n;++v){
if( lay[v]!= -1 || g[v][u]==0 ) continue; ///
lay[v]= lay[u]+1;
++gap[ lay[v] ];
que[tail++]= v;
}
}
}
// 每次走允许弧来找增广路,不存在允许弧时则重标号并退后一个节点;
int SAP(int n){
int v,ans=0,u=S;
bfs_init(n);
MM( pre, -1 );
while(lay[S]<n){
for(v=1;v<=n;++v){ //找一条允许弧;
if( g[u][v]>0 && lay[u]==lay[v]+1 )
break;
}
if(v<=n){ // 有允许弧;
pre[v]= u;
u=v;
if(v==T){
int cur_flow= maxint;
for(int i=T;i!=S;i=pre[i])
up_min( cur_flow, g[pre[i]][i] ); //由pre[]记录的增广路得到当前的最大可增流;
ans+= cur_flow;
//更新残余网络;
for(int i=T;i!=S;i=pre[i]){
g[ pre[i] ][i]-= cur_flow;
g[i][ pre[i] ]+= cur_flow;
}
u=S; // 再从源点S出发增广;
}
}
else{ // 没有允许弧;
int mindis= n;
for(int i=1;i<=n;++i){
if( g[u][i]>0 )
up_min( mindis, lay[i]+1 );
}
--gap[lay[u]];
if( gap[lay[u]]==0 ) return ans; // 出现断层,不存在增广路,已经得到了最大流;
++gap[mindis];
lay[u]= mindis; //重标号;
if(u!=S) u=pre[u]; //返回上一个节点;
}
}
return ans;
}
int main()
{
//freopen("1273.txt","r",stdin);
int n,m;
while(cin>>n>>m){
S=1, T=m;
MM(g,0);
while(n--){
int u,v,c;
scanf("%d%d%d",&u,&v,&c);
g[u][v]+= c; //有重边;
}
int ans= SAP(m);
cout<< ans <<endl;
}
}
带GAP优化的SAP模版+邻接矩阵
最新推荐文章于 2019-12-04 21:41:54 发布