众所周知,EK 增广路算法的效率是不如 dinic 算法的效率优的,因为 EK 每次 spfa 都会遍历整个残量网络,但最终只会修改一条增广路,dinic 这类阻塞式算法,一次 spfa 一次可以修改大量增广路,效率较高。
然而呢,我的 EK 算法用时 1.74s 初次 dinic 用时 1.92s,为什么呢?
dinic 每次 dfs 都会遍历大量节点,但是有相当一部分节点无法到达汇点,浪费时间;反观 EK 其每次都能精准修改一条增广路。
解决方法是倒序 spfa,disi 表示 i 点到汇点的距离,搜索时以汇点为起点,改一下路径计算即可。
code 节选
q.push_back(t), vis[t] = true, dis[t] = 0;
while (!q.empty()) {
for (int i = g[x]; i; i = e[i].nex) {
y = e[i].to;
if (dis[y] > dis[x] + e[i ^ 1].dis && e[i ^ 1].c) {
dis[y] = dis[x] + e[i ^ 1].dis;
if (!vis[y]) {
q.push_back(y);
vis[y] = true;
}
}
}
}
inline long long dfs(int p, long long flow) {
for (int i = now[p]; i && flow; i = e[i].nex) {
x = e[i].to;
if (dis[p] == dis[x] + e[i].dis && e[i].c && !vis[x]) {
f = dfs(x, Min(flow, e[i].c));
}
}
return ret;
}