最大流Dinic算法
摘自大神博客:
http://www.cnblogs.com/SYCstudio/p/7260613.html
增广路定理+分层图+当前弧优化
增广路:从源点出发不停的通过dfs出一条路径到汇点(直到无法走到汇点),每次dfs找出路径中最小残量,回溯时都减掉这个最小残量,并且连一条回边(原因如下图 :)

分层图:发现增广图处理下图问题非常耗时(s->v->u->t而不是s->v->t),所以每次dfs前都先用bfs求一次深度dep,且dfs时只允许低深度到高深度

当前弧优化:每次dfs不是从汇点的第一条边开始,而是用cur数组记录u循环到哪条边,以此来加速
上代码:
int n, m, s, t;
struct edge
{
int to, w, nx;
} e[N << 1];
int fi[N];
int ce = 1;
int dep[N];
bool vis[N];
int cur[N];
inline void add(int u, int v, int w)
{
e[++ce] = edge{v, w, fi[u]};
fi[u] = ce;
}
int bfs()
{
me(dep, 0);
queue<int> q;
q.push(s);
dep[s] = 1;//特别注意这里赋值个不为0的数,不然就是死循环!!!
while (!q.empty())
{
int u = q.front();
q.pop();
for (int i = fi[u]; ~i; i = e[i].nx)
{
int v = e[i].to;
if (e[i].w && !dep[v])
{
dep[v] = dep[u] + 1;
q.push(v);
}
}
}
return dep[t];
}
int dfs(int u, int flow)
{
if (u == t)
return flow;
for (int &i = cur[u]; ~i; i = e[i].nx)
{
int v = e[i].to;
if (e[i].w && dep[u] + 1 == dep[v])
{
int di = dfs(v, min(e[i].w, flow));
if (di)
{
e[i].w -= di, e[i ^ 1].w += di;
return di;
}
}
}
return 0;
}
int dinic(int s, int t)
{
int res = 0;
int cnt = 0;
while (bfs())
{
if (++cnt > 20)
break;
For(i, 1, n) cur[i] = fi[i];
while (int di = dfs(s, inf))
res += di;
}
return res;
}
int main()
{
#ifndef ONLINE_JUDGE
file("test");
#endif
me(fi, -1);
sdf(n), sdf(m), sdf(s), sdf(t);
while (m--)
{
int u, v, w;
sdf(u), sdf(v), sdf(w);
add(u, v, w), add(v, u, 0);
}
printf("%d", dinic(s, t));
return 0;
}

浙公网安备 33010602011771号