Как восстановить сам минимальный разрез после вычисления максимального потока?
Поток посчитал (Диниц), значение минимального разреза знаю — оно равно потоку. Но в задаче просят вывести сами рёбра минимального разреза (или множество вершин ). Как их найти, имея насыщенную остаточную сеть?
2 ответа
После того как maxflow завершился, в остаточной сети уже нет пути . Делаем простой обход:
- Запускаем BFS/DFS из только по рёбрам с положительной остаточной пропускной ().
- Множество достижимых вершин — это . Остальные — (туда точно попадёт ).
- Рёбра минимального разреза — это исходные рёбра такие, что , (по ним в остаточной сети течь нельзя — они насыщены).
vector<char> vis;
void reach(int v){
vis[v]=1;
for(int id:g[v]) if(e[id].cap>0 && !vis[e[id].to]) reach(e[id].to);
}
// после maxflow(s,t):
vis.assign(n,0); reach(s);
// S = {v : vis[v]}, рёбра разреза:
for(int v=0; v<n; v++) if(vis[v])
for(int id:g[v]) if(!(id&1)) { // только прямые рёбра исходного графа
int to=e[id].to;
if(!vis[to]) {
// (v, to) — ребро минимального разреза
}
}
Важно: разрез образуют только исходные (прямые) рёбра, идущие из в . Чтобы их отличать, либо помечайте флагом «настоящее ли это ребро», либо (как выше) опирайтесь на чётность индекса, если все исходные рёбра добавлялись через add_edge первыми в паре. Сумма их пропускных способностей обязана равняться значению потока — это хорошая проверка корректности.
Тонкость, которую легко прозевать: при подсчёте суммы используйте исходную пропускную способность , а не текущий остаток cap (который у насыщенного ребра равен 0). Поэтому если код переиспользует то же поле cap для остатка, сохраните оригинальные пропускные отдельно (orig_cap) при добавлении рёбер. Без этого вы получите правильное множество , но не сможете напечатать веса рёбер разреза.