EK 复杂度O(V*E*E)
#define N 204
int c[N][N];//边容量
int f[N][N];//边实际流量
int pre[N];//记录增广路径
int res[N];//残余网络
queue<int> qq;
void init(){
while(!qq.empty())qq.pop();
memset(c,0,sizeof(c));
memset(f,0,sizeof(f));
}
int EK(int s,int t){
int i,j;
int ans=0;
while(1){
memset(res,0,sizeof(res));
res[s] = MAX;//源点的残留网络要置为无限大!否则下面找增广路出错
pre[s] = -1;
qq.push(s);
//bfs找增广路径
while(!qq.empty()){
int x = qq.front();
qq.pop();
for(i=1;i<=t;i++){
if(!res[i] && f[x][i] < c[x][i]){
qq.push(i);
pre[i] = x;
res[i] = min(c[x][i] - f[x][i], res[x]);//这里类似dp,如果有增广路,那么res[t]就是增广路的最小权
}
}
}
if(res[t]==0)break;//找不到增广路就退出
int k = t;
while(pre[k]!=-1){
f[pre[k]][k] += res[t];//正向边加上新的流量
f[k][pre[k]] -= res[t];//反向边要减去新的流量,反向边的作用是给程序一个后悔的机会
k = pre[k];
}
ans += res[t];
}
return ans;
}
Dinic递归(推荐)
#define M 400
struct node {
int u, v, next, cap;
} edge[M*M];
int next[M], head[M], layer[M], Q[M * 2], mark[M];
int ecnt;
void init(){
ecnt= 0;
memset(head,-1,sizeof(head));
}
void add(int u, int v, int c) {
edge[ecnt].u = u;
edge[ecnt].v = v;
edge[ecnt].cap = c;
edge[ecnt].next = head[u];
head[u] = ecnt++;
edge[ecnt].u = v;
edge[ecnt].v = u;
edge[ecnt].cap = 0;
edge[ecnt].next = head[v];
head[v] = ecnt++;
}
bool BFS(int begin, int end) {
int i, l, h, k, y;
for (i = 0; i <= end; i++) layer[i] = -1;
layer[begin] = 0;
l = h = 0;
Q[l++] = begin;
while (h < l) {
k = Q[h++];
for (i = head[k]; i != -1; i = edge[i].next) {
y = edge[i].v;
if (edge[i].cap > 0 && layer[y] == -1) {
layer[y] = layer[k] + 1;
if (y == end)
return true;
Q[l++] = y;
}
}
}
return false;
}
int DFS(int x, int exp, int end) {
mark[x] = 1;
if (x == end)return exp;
int y, temp, i;
for (i = next[x]; i != -1; i = edge[i].next, next[x] = i) {
y = edge[i].v;
if (edge[i].cap > 0 && layer[y] == layer[x] + 1 && !mark[y]) {
if ((temp = (DFS(y, min(exp, edge[i].cap), end))) > 0) {
edge[i].cap -= temp;//流完后正向流表示剩余流量
edge[i^1].cap += temp;//流完后反向流表示正向流的流量
return temp;
}
}
}
return 0;
}
int Dinic_flow(int begin, int end) {
int i, ans = 0, flow;
while (BFS(begin, end)) {
for (i = 0; i <= end; i++)next[i] = head[i];
while (true) {
for (i = 0; i <= end; i++) mark[i] = 0;
flow = DFS(begin, INT_MAX, end);
if (flow == 0)break;
ans += flow;
}
}
return ans;
}
Dinic非递归 复杂度O(V^2*E)
#define N 20100
#define sta que
//静态邻接表
int level[N];
int p[N],p1[N];
int ecnt;
int que[N];
int n,m;
struct edge{
int v,next;
int c;
}e[900000];
void init(){
ecnt = 0;
memset(p,-1,sizeof(p));
}
void insert(int u,int v,int c,int w){
e[ecnt].v = v;
e[ecnt].c = c;
e[ecnt].next = p[u];
p[u] = ecnt++;
e[ecnt].v = u;
e[ecnt].c = w;
e[ecnt].next = p[v];
p[v] = ecnt++;
}
int Dinic(int st,int ed){
int ans = 0;
int i,u,v,c;
int head,rear,top;
while(1){//重建层次图
memset(level,0,sizeof(level));
head = rear = 0;
level[st]=1;
que[rear++]=st;
while(head<rear){
u = que[head++];
for(i=p[u];i!=-1;i=e[i].next){
v = e[i].v;
c = e[i].c;
if(c && level[v] == 0){
level[v] = level[u]+1;
que[rear++]=v;
}
}
}
if(level[ed] == 0){//无增广路
break;
}
memcpy(p1,p,sizeof(p1));
top = -1;
while(1){
if(top<0){
for(i=p1[st];i!=-1;i=e[i].next){
v = e[i].v;
c = e[i].c;
if(c && p1[v] != -1 && level[v] == 2)break;
}
if(i>=0){
sta[++top] = i;
p1[st] = e[i].next;
} else break;
}
u = e[sta[top]].v;
if(u == ed){//找到一条增广路
//计算流的可改进量,并记录离源点最远的可能会组成下一条增广路径的边
int dd = MAX,index = -1;
for(i=0;i<=top;i++){
if(dd>e[sta[i]].c){
dd = e[sta[i]].c;
index = i;
}
}
ans += dd;
//调整残余网络
for(i=0;i<=top;i++){
//直接由上一残余网络计算当前残余网络 见导论P401
e[sta[i]].c -= dd;
e[sta[i]^1].c += dd;
}
//回溯到路径上某个可能继续增广的顶点,若该顶点也无法增广,则回溯到前一个顶点(1)
for(i=0;i<=top;i++){
if(e[sta[i]].c==0){
top = index-1;
break;
}
}
} else {
for(i=p1[u];i!=-1;i = e[i].next){
v = e[i].v;
c = e[i].c;
if(c && p1[v]!=-1 && level[u]+1 == level[v])break;
}
if(i!=-1){
sta[++top] = i;
p1[u] = e[i].next;//若沿着边i找到了增广路,则p1会被从新初始化;否则断定从边i出发无法到达汇点,以后搜索增广路将不再考虑此边。估可将其忽略
} else {
p1[u] = -1;
top--;
}
}
}
}
return ans;
}
SAP非递归 复杂度O(V*V*E)
#define N 440
#define M N*N
#define inf 1<<30
int head[N];
struct Edge {
int v,next,c;
}edge[M];
int ecnt;
void init(){
ecnt = 0;
memset(head,-1,sizeof(head));
}
void add(int u,int v,int w) {
edge[ecnt].v=v;
edge[ecnt].c=w;
edge[ecnt].next=head[u];
head[u]=ecnt++;
edge[ecnt].v=u;
edge[ecnt].c=0;
edge[ecnt].next=head[v];
head[v]=ecnt++;
}
int sap(int s,int t,int nodenum){ //源,汇,汇点编号(非点数)
int pre[N],cur[N],dis[N],gap[N];
int flow=0,aug=inf;
int u;
bool flag;
int i,j;
for(i=0;i<=nodenum;i++){
cur[i]=head[i];
gap[i]=dis[i]=0;
}
gap[s]=nodenum;
u=pre[s]=s;
while(dis[s]<nodenum){
flag=0;
for(j=cur[u];j!=-1;j=edge[j].next){
int v=edge[j].v;
if(edge[j].c>0 && dis[u]==dis[v]+1){
flag=1;
cur[u] = j;
aug = min(aug,edge[j].c);
pre[v]=u;
u=v;
if(u==t){
flow+=aug;
while(u!=s){
u=pre[u];
edge[cur[u]].c -= aug; //边的正流不断减少
edge[cur[u]^1].c += aug; //反流增加
}
aug=inf;
}
break;
}
}
if(flag)continue;
if(--gap[dis[u]] == 0)break;
for(dis[u] = nodenum, j=head[u]; j!=-1; j=edge[j].next){
int v=edge[j].v;
if(edge[j].c>0 && dis[v]<dis[u]){
dis[u]=dis[v];
cur[u]=j;
}
}
dis[u]++;
gap[dis[u]]++;
u=pre[u];
}
return flow;
}
ISAP + GAP优化 复杂度O(V^2*E)
#define N 20010
#define M 500010
int n,m;//n为点数 m为边数
int h[N];
int gap[N];
int p[N],ecnt;
int source,sink;
struct edge{
int v;
int next;//下一条边的编号
int val;//边权值
}e[M];
inline void init(){memset(p,-1,sizeof(p));ecnt=0;}
//有向
inline void add1(int from,int to,int val){
e[ecnt].v=to;
e[ecnt].val=val;
e[ecnt].next=p[from];
p[from]=ecnt++;
swap(from,to);
e[ecnt].v=to;
e[ecnt].val=0;
e[ecnt].next=p[from];
p[from]=ecnt++;
}
//无向
inline void add2(int from,int to,int val){
e[ecnt].v=to;
e[ecnt].val=val;
e[ecnt].next=p[from];
p[from]=ecnt++;
swap(from,to);
e[ecnt].v=to;
e[ecnt].val=val;
e[ecnt].next=p[from];
p[from]=ecnt++;
}
inline int dfs(int pos,int cost){
if (pos==sink){
return cost;
}
int j,minh=n-1,lv=cost,d;
for (j=p[pos];j!=-1;j=e[j].next){
int v=e[j].v,val=e[j].val;
if(val>0){
if (h[v]+1==h[pos]){
if (lv<e[j].val) d=lv;
else d=e[j].val;
d=dfs(v,d);
e[j].val-=d;
e[j^1].val+=d;
lv-=d;
if (h[source]>=n) return cost-lv;
if (lv==0) break;
}
if (h[v]<minh) minh=h[v];
}
}
if (lv==cost){
--gap[h[pos]];
if (gap[h[pos]]==0) h[source]=n;
h[pos]=minh+1;
++gap[h[pos]];
}
return cost-lv;
}
int sap(int st,int ed){
source=st;
sink=ed;
int ans=0;
memset(gap,0,sizeof(gap));
memset(h,0,sizeof(h));
gap[st]=n;
while (h[st]<n){
ans+=dfs(st,INT_MAX);
}
return ans;
}