这道题目就是最大流的模板题,以前只会打Dinic,后来知道这个效率更高的算法后,匆忙学了一波。
这道题目注意一下他两个点间可能有多条渠道,其他没什么陷阱,只要把两点间渠道的容量加起来就可以了。
ISAP算法,他寻找最短增广路的方法与Dinic相同,区别在于一个是找不到增广路的时候重新构建分层图,而ISAP引入一个d(i)函数表示残量网络种结点i到汇点T的距离的最小值(下界),增广时,只允许沿着d(i)=d(j)+1的弧走,每当无法再增广下去时,修改d(i)=min{d(j)|(i,j)是残量网络中的弧}+1,然后往回走(此步骤被称为Retreat),如果残量网络中没有从i出发的弧了,就让d(i)=n,如果d(1)=n,那么就没有增广路了。
ISAP算法中,还有一个优化,叫gap。用数组num[x]存储距离汇点T为x距离的结点个数,这样,当每次更新d(i)时,比如距离从x变为了y,那么num[x]--,num[y]++,如果num[x]为0了,那么说明s-t不连通,因为随着增广路的寻找,残量网络中的弧减少 ,d(i)只增不减,即y>x,则x把图分成各一半,也就是说如果num[x]为0,说明num[x+1]以上的点与num[x-1]一下的点之间是不连通的,好比一列轨道,中间少了一轨,就成了两段。自己好好体会体会一下,应该挺容易明白的。
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
#define max_N 210
#define max_M 210
#define INF 2147483647
using namespace std;
int n,m;
int d[max_M],p[max_M],cur[max_M],num[max_M];
int cap[max_M][max_M],flow[max_M][max_M];
int x,y,zhi,tot;
bool vis[max_M];
bool bfs(){
memset(vis,0,sizeof(vis));
for(int i=1;i<=m;i++) d[i]=n;
queue <int> que;
que.push(m);
vis[m]=1;
d[m]=0;
while(!que.empty()){
int u=que.front();que.pop();
for(int i=1;i<=m;i++){
if(i==u) continue;
if(cap[i][u]&&!vis[i]){
d[i]=d[u]+1;
vis[i]=1;
que.push(i);
}
}
}
return vis[1];
}
int Augment(){
int x=m,a=INF;
while(x!=1){
a=min(a,cap[p[x]][x]-flow[p[x]][x]);
x=p[x];
}
x=m;
while(x!=1){
flow[p[x]][x]+=a;
flow[x][p[x]]-=a;
x=p[x];
}
return a;
}
int Maxflow(int s,int t){
if(!bfs())return 0;
int Flow=0,x=1;
memset(num,0,sizeof(num));
memset(cur,0,sizeof(cur));
for(int i=0;i<=m;i++)num[d[i]]++;
while(d[s]<m){
if(x==m){
Flow+=Augment();
x=s;
}
bool ok=0;
for(int i=cur[x];i<=m;i++){
if(i==x||i==0) continue;
if(cap[x][i]>flow[x][i]&&d[x]==d[i]+1){ //Advance
ok=1;
p[i]=x;
cur[x]=i;
x=i;
break;
}
}
if(!ok){ //retreat
int ans=m-1;
for(int i=1;i<=m;i++){
if(i==x) continue;
if(cap[x][i]>flow[x][i])ans=min(ans,d[i]);
}
if(--num[d[x]]==0) break; //gap优化
num[d[x]=ans+1]++;
cur[x]=1;
if(x!=s) x=p[x];
}
}
return Flow;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d%d%d",&x,&y,&zhi);
if(x==y) continue;
cap[x][y]+=zhi;
}
printf("%d",Maxflow(1,m));
return 0;
}
下面贴代码: