题目地址:http://poj.org/problem?id=1273
网络流第一发!isap还不算太难理解,就是略麻烦。。第一次写,调试了好长时间。这题是一纯纯的模板题。所以可以将本题代码用作模板。
#include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <queue> #include <map> #include <algorithm> using namespace std; //head存储前向星的有相同起点的弧,num存储各层剩余节点数目,d存储各节点的层数,cur存储当前弧,pre存储路径,即当前节点的上一个节点,用于回溯。 int head[1000], num[1000], d[1000], cur[1000], n, m, cnt, s, t, q[100000], nv, pre[1000]; int maxint=99999999; struct node { int v, cap, next; } edge[1000]; void add(int u, int v, int cap) { //加正向弧 edge[cnt].v=v; edge[cnt].cap=cap; edge[cnt].next=head[u]; head[u]=cnt++; //加反向弧 edge[cnt].v=u; edge[cnt].cap=0; edge[cnt].next=head[v]; head[v]=cnt++; } void bfs()//用bfs对每个节点分层 { int i, j; memset(num,0,sizeof(num)); memset(d,-1,sizeof(d)); int f1=0,f2=0; q[f1++]=t; d[t]=0; num[0]=1; while(f1>=f2) { int u=q[f2++]; for(i=head[u]; i!=-1; i=edge[i].next) { int v=edge[i].v; if(d[v]!=-1) continue; d[v]=d[u]+1;//此节点的层数是上一个节点下一层 num[d[v]]++;//该层数的节点数+1 q[f1++]=v; } } } void isap() { memcpy(cur,head,sizeof(cur)); bfs(); int flow =0, u=pre[s]=s, i; while(d[s]<nv)//如果d【s】大于nv,说明有断层 { if(u==t) { int f=maxint, pos; for(i=s; i!=t; i=edge[cur[i]].v)//找该路上的最小残余流量 { if(f>edge[cur[i]].cap) { f=edge[cur[i]].cap; pos=i; } } for(i=s; i!=t; i=edge[cur[i]].v)//将该路上的所有流量都减去最小残余流量 { edge[cur[i]].cap-=f; edge[cur[i]^1].cap+=f; } flow+=f;//加入总流量 u=pos; } for(i=cur[u];i!=-1;i=edge[i].next) { if(d[edge[i].v]+1==d[u]&&edge[i].cap) { break; } } if(i!=-1)//如果找到可行增广路,更新 { cur[u]=i;//更新当前弧 pre[edge[i].v]=u;//更新路径 u=edge[i].v;//回溯 } else { if(--num[d[u]]==0) break; //gap优化 int mind=nv; for(i=head[u];i!=-1;i=edge[i].next)//找最小层次 { if(edge[i].cap&&mind>d[edge[i].v]) { cur[u]=i; mind=d[edge[i].v]; } } d[u]=mind+1; num[d[u]]++; u=pre[u]; } } printf("%d\n",flow); } int main() { int i, a, b, c; while(scanf("%d%d",&n,&m)!=EOF) { memset(head,-1,sizeof(head)); cnt=0; while(n--) { scanf("%d%d%d",&a,&b,&c); add(a,b,c);//加边 } s=1; t=m; nv=t+1; isap(); } return 0; }