算法复习——网络流模板(ssoj)
题目:
题目描述
有 n(0<n<=1000)个点,m(0<m<=1000)条边,每条边有个流量 h(0<=h<35000),求从点 start 到点 end 的最大流。
输入格式
第一行:4 个整数,分别是 n,m,start,end 。
接下来有 m 行,每行四个三个整数 a,b,h,分别表示 a 到 b,流量为 h 的一条边。
输出格式
输出从点 start 到点 end 的最大流。
样例数据 1
输入 [复制]
7 14 1 7
1 2 5
1 3 6
1 4 5
2 3 2
2 5 3
3 2 2
3 4 3
3 5 3
3 6 7
4 6 5
5 6 1
6 5 1
5 7 8
6 7 7
输出
14
备注
【样例图示】
【数据范围】
0<n,m<=1000;h<=35000
方法:
网络流基础模板
代码:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<ctime> #include<cctype> #include<cstring> #include<string> #include<algorithm> #include<queue> using namespace std; queue<int>que; const int N=100005; const int inf=1e+9; int first[N],go[N*2],next[N*2],rest[N*2],lev[N],tot=1; int n,m,src,des,ans; inline bool bfs() { for(int i=1;i<=n;i++) lev[i]=-1; int tail,head,que[N]; que[tail=1]=src; lev[src]=0; for(head=1;head<=tail;head++) { int u=que[head],v; for(int e=first[u];e;e=next[e]) { if(rest[e]&&lev[v=go[e]]==-1) { lev[v]=lev[u]+1; que[++tail]=v; if(v==des) return true; } } } return false; } inline int dinic(int u,int flow) { if(u==des) return flow; int res=0,temp,v; for(int e=first[u];e;e=next[e]) { if(rest[e]&&lev[v=go[e]]>lev[u]) { temp=dinic(v,min(rest[e],flow-res)); if(temp) { res+=temp; rest[e]-=temp,rest[e^1]+=temp; if(res==flow) break; } } } if(res!=flow) lev[u]=-1; return res; } inline void comb(int u,int v,int w) { next[++tot]=first[u],first[u]=tot,rest[tot]=w,go[tot]=v; next[++tot]=first[v],first[v]=tot,rest[tot]=0,go[tot]=u; } inline void maxflow() { while(bfs()) ans+=dinic(src,inf); } int main() { //freopen("a.in","r",stdin); //freopen("a.out","w",stdout); scanf("%d%d%d%d",&n,&m,&src,&des); int u,v,w; for(int i=1;i<=m;i++) { scanf("%d%d%d",&u,&v,&w); comb(u,v,w); } maxflow(); cout<<ans<<endl; return 0; }