EK
//Max_flow
//@2018/05/02 Wednesday
//EK algorithm [Edmonds Karp] O(V*E^2) O(v^2)
//by Tawn
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3;
const int INF = 0x3f3f3f3f;
int n,m; //n - Vertices m - edges
int pre[maxn]; //record predecesor and sign if it is visited
int cap[maxn][maxn]; //record the capacity of residual network
int flow[maxn]; //record the residual flow from starting vertex to current vertex
queue <int> q;
int bfs(int st, int ed)
{
memset(pre,-1,sizeof(pre));
while(!q.empty()) q.pop();
pre[st] = 0;
flow[st] = INF;
q.push(st);
while(!q.empty())
{
int t = q.front();
q.pop();
if(t == ed) break;
for(int i = 1; i <= n; i++)
{
if(pre[i] == -1 && cap[t][i] > 0)
{
pre[i] = t;
flow[i] = min(flow[t],cap[t][i]);
q.push(i);
}
}
}
if(pre[ed] == -1) return -1;
else return flow[ed];
}
int EK(int st, int ed)
{
int res = 0; //the augmenting flow
int sum = 0; //the max_flow
while((res = bfs(st,ed)) != -1)//argumenting path
{
int k = ed;
while(k != st)
{
int f = pre[k];
cap[f][k] -= res;
cap[k][f] += res;//reversible edge
k = f;
}
sum += res;
}
return sum;
}
int main()
{
int s,t,c;
scanf("%d%d",&n,&m);
memset(cap,0,sizeof(cap));
for(int i = 0; i < m; i++)
{
scanf("%d%d%d",&s,&t,&c);
cap[s][t] = c;
}
int ans = EK(1,n);
printf("%d\n",ans);
return 0;
}
Dinic
当前弧优化,维护一个cur数组,放入所有的h[i]];每次dfs的时候用int &i = cur[x];
//Max_flow
//@2018/05/04 Friday
//Dinic O(n^2 * m) O(m*3*2)
//by Tawn
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 200 + 10;
const int maxm = 200 + 10;
int n,m;
int l[maxn];//记录层数
int h[maxn];//链式前向星
int cur[maxn];
int tot = 0;
struct edge
{
int to;
int c;
int next;
edge(int x = 0, int y = 0, int z = 0) : to(x), c(y), next(z) {}
}es[maxm*2];//记录边 注意是2倍
void add_edge(int u, int v, int c)
{
es[tot] = edge(v,c,h[u]);
h[u] = tot++;
}
bool bfs(int s, int t)
{
memset(l,0,sizeof(l));
l[s] = 1;
queue <int> q;
q.push(s);
while(!q.empty())
{
int u = q.front();
q.pop();
if(u == t) return true;
for(int i = h[u]; i != -1; i = es[i].next)
{
int v = es[i].to;
if(!l[v] && es[i].c) {l[v] = l[u] + 1; q.push(v);}
}
}
return false;
}
int dfs(int x, int t, int mf)
{
if(x == t) return mf;
int ret = 0;
for(int i = cur[x]; i != -1; i = es[i].next)
{
if(es[i].c && l[x] == l[es[i].to] - 1)
{
int f = dfs(es[i].to,t,min(es[i].c,mf - ret));
es[i].c -= f;
es[i^1].c += f;
ret += f;
if(ret == mf) return ret;
}
}
return ret;
}
int dinic(int s, int t)
{
int ans = 0;
while(bfs(s,t))
{
for(int i = 0; i <= n; i++) cur[i] = h[i];
ans += dfs(s,t,INF);
}
return ans;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
tot = 0;
memset(h,-1,sizeof(h));
int u,v,c;
for(int i = 0; i < m; i++)
{
scanf("%d%d%d",&u,&v,&c);
add_edge(u,v,c);
add_edge(v,u,0);//增加反向边
}
int ans = dinic(1,n);
printf("%d\n",ans);
}
return 0;
}
SAP
//Max_flow
//@2018/05/04 Friday
//SAP O(n^2 * m) O(m*3*2)
//by Tawn
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 200 + 10;
const int maxm = 200 + 10;
int n,m;
int head[maxn];//链式前向星
int tot = 0;
struct edge
{
int to;
int c;
int next;
edge(int x = 0, int y = 0, int z = 0) : to(x), c(y), next(z) {}
}es[maxm*2];//记录边 注意是2倍
void add_edge(int u, int v, int c)
{
es[tot] = edge(v,c,head[u]);
head[u] = tot++;
}
int SAP(int s, int t)
{
int numh[maxn],h[maxn],ce[maxn],pre[maxn];
//numh 记录gap优化的统计高度数量数组,h 距离标号数组,ce 当前弧,pre前驱数组
int f, ans = 0, u, temp, neck, i; //初始化最大流为0
memset(h,0,sizeof(h));
memset(numh,0,sizeof(numh));
memset(pre,-1,sizeof(pre));
for(i = 1; i <= n; i++) ce[i] = head[i];
numh[0] = n;
u = s;
while(h[s] < n)
{
//寻找增广路
if(u == t)
{
f = INF;
for(i = s; i != t; i = es[ce[i]].to)
{
if(f > es[ce[i]].c)
{
neck = i;
f = es[ce[i]].c;
}
}
for(i = s; i != t; i = es[ce[i]].to)
{
temp = ce[i];
es[temp].c -= f;
es[temp^1].c += f;
}
ans += f;
u = neck;
}
//寻找可行弧
for(i = ce[u]; i != -1; i = es[i].next)
if(es[i].c && h[u] == h[es[i].to] + 1) break;
//寻找增广路
if(i != -1)
{
ce[u] = i;
pre[es[i].to] = u;
u = es[i].to;
}
else
{
if(!--numh[h[u]]) break; //gap optimization
ce[u] = head[u];
for(temp = n, i = head[u]; i != -1; i = es[i].next)
if(es[i].c) temp = min(temp, h[es[i].to]);
h[u] = temp + 1;
++numh[h[u]];
if(u != s) u = pre[u];//重标号并且从当前点前驱重新增广
}
}
return ans;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
tot = 0;
memset(head,-1,sizeof(head));
int u,v,c;
for(int i = 0; i < m; i++)
{
scanf("%d%d%d",&u,&v,&c);
add_edge(u,v,c);
add_edge(v,u,0);//增加反向边
}
int ans = SAP(1,n);
printf("%d\n",ans);
}
return 0;
}