最大流/最小割模板(isap) POJ1273

时间:2022-01-04 20:38:38

isap模板核心代码:

 //d[]为距离标号数组,d[i]表示节点i到汇点的距离
//gap[]为GAP优化数组,gap[i]表示到汇点距离为i的节点个数
int dfs(int k,int flow){//flow为当前剩余流量
int i;
if(k==t)return flow;
int sum=;
for(i=head[k];i;i=e[i].nxt){
int v=e[i].to;
if(e[i].f&&d[k]==d[v]+){//判断能否通过流量以及走的是否为最短路
int f=dfs(v,min(flow-sum,e[i].f));//注意是flow-sum,要将已用过的流量减去
sum+=f;head[k]=i;//当前弧优化
e[i].f-=f;e[i^].f+=f;
if(sum==flow||d[s]==cnt)return sum;//流量全部流完或者达到退出条件则返回
}
}
if((--gap[d[k]])==)d[s]=cnt;//若gap[]出现断层,则无法增广
gap[++d[k]]++;//
head[k]=h[k];//
return sum;
} int sap(){
memcpy(h,head,sizeof(head));
memset(d,,sizeof(d));
memset(gap,,sizeof(gap));
gap[]=cnt;
int flow=;
while(d[s]<cnt)
flow+=dfs(s,inf);
return flow;
}

一道水题:poj1273

题意:现在有m个池塘(从1到m开始编号,1为源点,m为汇点),及n条水渠,给出这n条水渠所连接的点和所能流过的最大流量,求从源点到汇点能流过的最大流量。

有多组数据!网上查的中文题意没说,样例只给了一组,WA。

 #include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define repu(i,x,y) for(int i=x;i<=y;i++)
using namespace std; struct edge{int to,nxt,f;}e[];
const int inf=1e9;
int head[],h[],d[],gap[],n,m,ne=,s,t,cnt; void add(int u,int v,int f){
e[++ne]=(edge){v,head[u],f};head[u]=ne;
} //d[]为距离标号数组,d[i]表示节点i到汇点的距离
//gap[]为GAP优化数组,gap[i]表示到汇点距离为i的节点个数
int dfs(int k,int flow){//flow为当前剩余流量
int i;
if(k==t)return flow;
int sum=;
for(i=head[k];i;i=e[i].nxt){
int v=e[i].to;
if(e[i].f&&d[k]==d[v]+){//判断能否通过流量以及走的是否为最短路
int f=dfs(v,min(flow-sum,e[i].f));//注意是flow-sum,要将已用过的流量减去
sum+=f;head[k]=i;//当前弧优化
e[i].f-=f;e[i^].f+=f;
if(sum==flow||d[s]==cnt)return sum;//流量全部流完或者达到退出条件则返回
}
}
if((--gap[d[k]])==)d[s]=cnt;//若gap[]出现断层,则无法增广
gap[++d[k]]++;//
head[k]=h[k];//
return sum;
} int sap(){
memcpy(h,head,sizeof(head));
memset(d,,sizeof(d));
memset(gap,,sizeof(gap));
gap[]=cnt;
int flow=;
while(d[s]<cnt)
flow+=dfs(s,inf);
return flow;
} int main(){
int u,v,f;
while(scanf("%d%d",&n,&m)!=EOF){
ne=;
memset(e,,sizeof(e));
memset(head,,sizeof(head));
repu(i,,n){
scanf("%d%d%d",&u,&v,&f);
add(u,v,f);add(v,u,);
}
cnt=m;s=;t=m;
int ans=sap();
printf("%d\n",ans);
}
return ;
}