网络流模版

#include <cstring>
#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

const int MAXN=100010;  //点的个数
const int MAXM=400010;  //边的个数
const int INF=0x3f3f3f3f;

struct Edge
{
    int to,next,cap,flow;  //cap代表每条边的容量,flow代表每条边当前的流量大小
}edge[MAXM];

int tol;            //代表当前边的条数(编号)
int head[MAXN];
int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN];
//gap:和t的最短距离等于i的结点数量
//dep:每个点的层数(深度)
void init() { tol=0; memset(head,-1,sizeof(head)); } void addEdge(int u,int v,int w,int rw=0)  //加边,如果是单向边的话,传递3个参数(边的起始点,边的终止点,边容量大小),如果是双向边,最后一个参数记录反向边的容量大小 { edge[tol].to=v; edge[tol].cap=w; edge[tol].next=head[u]; edge[tol].flow=0; head[u]=tol++; edge[tol].to=u; edge[tol].cap=rw; edge[tol].next=head[v]; edge[tol].flow=0; head[v]=tol++; //cout<<"tol"<<tol<<endl; } int sap(int start,int end,int N)    //start代表源点的编号,end代表汇点的编号,N代表总共点的个数,返回值ans代表最大流的流量大小 { memset(gap,0,sizeof(gap)); memset(dep,0,sizeof(dep)); memcpy(cur,head,sizeof(head)); int u=start; pre[u]=-1; gap[0]=N; int ans=0; while(dep[start]<N) { if(u==end) { int Min=INF; for(int i=pre[u];i!=-1;i=pre[edge[i^1].to]) if(Min>edge[i].cap-edge[i].flow) Min=edge[i].cap-edge[i].flow; for(int i=pre[u];i!=-1;i=pre[edge[i^1].to]) { //cout<<edge[i].to<<endl; edge[i].flow+=Min; edge[i^1].flow-=Min; } u=start; ans+=Min; continue; } bool flag=false; int v; for(int i=cur[u];i!=-1;i=edge[i].next) { v=edge[i].to; if(edge[i].cap-edge[i].flow&&dep[v]+1==dep[u]) { flag=true; cur[u]=pre[v]=i; break; } } if(flag) { u=v; continue; } int Min=N; for(int i=head[u];i!=-1;i=edge[i].next) { if(edge[i].cap-edge[i].flow&&dep[edge[i].to]<Min) { Min=dep[edge[i].to]; cur[u]=i; } } gap[dep[u]]--; if(!gap[dep[u]]) return ans; dep[u]=Min+1; gap[dep[u]]++; if(u!=start) u=edge[pre[u]^1].to; } return ans; }
原文地址:https://www.cnblogs.com/wsruning/p/5712503.html