From 20dc3ca88e4639350f3c88ae67a87c2a21f4a368 Mon Sep 17 00:00:00 2001 From: Igor Date: Tue, 9 Jul 2024 17:55:13 -0300 Subject: [PATCH 1/3] feat: add gomory-hu implementation and description --- src/graph/gomory_hu.md | 88 ++++++++++++++++++++++++++++++++++++++++++ src/navigation.md | 1 + 2 files changed, 89 insertions(+) create mode 100644 src/graph/gomory_hu.md diff --git a/src/graph/gomory_hu.md b/src/graph/gomory_hu.md new file mode 100644 index 000000000..2e3567927 --- /dev/null +++ b/src/graph/gomory_hu.md @@ -0,0 +1,88 @@ +# Gomory Hu Tree + +## Definition + +The gomory-hu tree of an undirected graph with capacities consists of a weighted tree that condenses information from all the *s-t cuts* for all s-t vertex pairs in the graph. Naively, one must think that $O(|V|^2)$ flow computations are needed to build this data structure, but actually it can be shown that only $|V| - 1$ flow computations are needed. Once the tree is constructed, we can get the minimum cut between two vertices *s* and *t* by querying the minimum weight edge in the unique *s-t* path. + +## Gusfield's Simplification Algorithm + +We can say that two cuts (X, Y) and (U, V) *cross* if all four set intersections $X \cap U$, $X \cap V$, $Y \cap U$, $Y \cap V$ are nonempty. Most of the work of the original gomory-hu method is involved in maintaining the noncrossing condition. The following simpler, yet efficient method, proposed by Gusfield uses crossing cuts to produce equivalent flow trees. + +## Complexity + +The algorithm total complexity is $\mathcal{O}(V*MaxFlow)$, wich means that the overall complexity depends on the algorithm that was choosen to find the maximum flow. + +### Implementation +This implementation considers the Gomory-Hu tree as a struct with methods: + +- The maximum flow algorithm must also be a struct with methods, in the implementation bellow we utilize Dinic's algorithm to calculate the maximum flow. + +- The algorithm is 0-indexed and will root the tree in node 0. + +- The method *solve* returns the list of edges of the Gomory-Hu tree. + +```{.cpp file=gomoryhu} +struct gomory_hu { + struct edg{ + int u, v, cap; + }; + + Dinic dinic; // you can change your Max Flow algorithm here + // !! if you change remember to make it compatible with the rest of the code !! + + vector edgs; + + void add_edge(int u, int v, int cap) { // the edges are already bidirectional + edgs.push_back({u, v, cap}); + } + + vector vis; + + void dfs(int a) { + if (vis[a]) return; + vis[a] = 1; + for (auto &e : dinic.adj[a]) + if (e.c - e.flow() > 0) + dfs(e.to); + } + + vector> solve(int n) { + vector> tree_edges(n); // if i > 0, stores pair(cost, parent). + + for (int i = 1; i < n; i++) { + dinic = Dinic(n); + + for (auto &e : edgs) dinic.addEdge(e.u, e.v, e.cap); + tree_edges[i].first = dinic.calc(i, tree_edges[i].second); + + vis.assign(n, 0); + dfs(i); + + for (int j = i + 1; j < n; j++) { + if (tree_edges[j].second == tree_edges[i].second && vis[j]) + tree_edges[j].second = i; + } + } + + return tree_edges; + } +}; +``` + +## Task examples + +Here are some examples of problems related to the Gomory-Hu tree: + +- Given a weighted and connected graph, find the minimun s-t cut for all pair of vertices. + +- Given a weighted and connected graph, find the minimum/maximum s-t cut among all pair of vertices. + +- Find an approximate solution for the [Minimum K-Cut problem](https://en.wikipedia.org/wiki/Minimum_k-cut). + +## Practice Problems + +- [Codeforces - Juice Junctions](https://codeforces.com/gym/101480/attachments) + +- [Codeforces - Honeycomb](https://codeforces.com/gym/103652/problem/D) + +- [Codeforces - Pumping Stations](https://codeforces.com/contest/343/problem/E) diff --git a/src/navigation.md b/src/navigation.md index 05c662e50..8f70c2720 100644 --- a/src/navigation.md +++ b/src/navigation.md @@ -189,6 +189,7 @@ search: - [Flows with demands](graph/flow_with_demands.md) - [Minimum-cost flow](graph/min_cost_flow.md) - [Assignment problem](graph/Assignment-problem-min-flow.md) + - [All-pairs minimum cut - Gomory Hu](graph/gomory_hu.md) - Matchings and related problems - [Bipartite Graph Check](graph/bipartite-check.md) - [Kuhn's Algorithm - Maximum Bipartite Matching](graph/kuhn_maximum_bipartite_matching.md) From a40adf7b9badbdfc5a2bd7770dc018d27cbf8728 Mon Sep 17 00:00:00 2001 From: Igor Date: Tue, 9 Jul 2024 18:29:06 -0300 Subject: [PATCH 2/3] fix(gomory-hu): typos and improve style --- src/graph/gomory_hu.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/graph/gomory_hu.md b/src/graph/gomory_hu.md index 2e3567927..d983efe72 100644 --- a/src/graph/gomory_hu.md +++ b/src/graph/gomory_hu.md @@ -6,7 +6,7 @@ The gomory-hu tree of an undirected graph with capacities consists of a weighted ## Gusfield's Simplification Algorithm -We can say that two cuts (X, Y) and (U, V) *cross* if all four set intersections $X \cap U$, $X \cap V$, $Y \cap U$, $Y \cap V$ are nonempty. Most of the work of the original gomory-hu method is involved in maintaining the noncrossing condition. The following simpler, yet efficient method, proposed by Gusfield uses crossing cuts to produce equivalent flow trees. +We can say that two cuts $(X, Y)$ and $(U, V)$ *cross* if all four set intersections $X \cap U$, $X \cap V$, $Y \cap U$, $Y \cap V$ are nonempty. Most of the work of the original gomory-hu method is involved in maintaining the noncrossing condition. The following simpler, yet efficient method, proposed by Gusfield uses crossing cuts to produce equivalent flow trees. ## Complexity @@ -15,11 +15,11 @@ The algorithm total complexity is $\mathcal{O}(V*MaxFlow)$, wich means that the ### Implementation This implementation considers the Gomory-Hu tree as a struct with methods: -- The maximum flow algorithm must also be a struct with methods, in the implementation bellow we utilize Dinic's algorithm to calculate the maximum flow. +- The maximum flow algorithm must also be a struct with methods, in the implementation below we utilize Dinic's algorithm to calculate the maximum flow. - The algorithm is 0-indexed and will root the tree in node 0. -- The method *solve* returns the list of edges of the Gomory-Hu tree. +- The method *solve* returns a list that contains for each index $i$ the cost of the edge connecting $i$ and its parent, and the parent number. ```{.cpp file=gomoryhu} struct gomory_hu { From c278efac361dde9901fb56105f5cac703417a777 Mon Sep 17 00:00:00 2001 From: Igor Date: Tue, 9 Jul 2024 19:09:11 -0300 Subject: [PATCH 3/3] feat(gomory-hu): add step-by-step description of the algorithm --- src/graph/gomory_hu.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/graph/gomory_hu.md b/src/graph/gomory_hu.md index d983efe72..5ea241016 100644 --- a/src/graph/gomory_hu.md +++ b/src/graph/gomory_hu.md @@ -2,12 +2,22 @@ ## Definition -The gomory-hu tree of an undirected graph with capacities consists of a weighted tree that condenses information from all the *s-t cuts* for all s-t vertex pairs in the graph. Naively, one must think that $O(|V|^2)$ flow computations are needed to build this data structure, but actually it can be shown that only $|V| - 1$ flow computations are needed. Once the tree is constructed, we can get the minimum cut between two vertices *s* and *t* by querying the minimum weight edge in the unique *s-t* path. +The gomory-hu tree of an undirected graph $G$ with capacities consists of a weighted tree that condenses information from all the *s-t cuts* for all s-t vertex pairs in the graph. Naively, one must think that $O(|V|^2)$ flow computations are needed to build this data structure, but actually it can be shown that only $|V| - 1$ flow computations are needed. Once the tree is constructed, we can get the minimum cut between two vertices *s* and *t* by querying the minimum weight edge in the unique *s-t* path. ## Gusfield's Simplification Algorithm We can say that two cuts $(X, Y)$ and $(U, V)$ *cross* if all four set intersections $X \cap U$, $X \cap V$, $Y \cap U$, $Y \cap V$ are nonempty. Most of the work of the original gomory-hu method is involved in maintaining the noncrossing condition. The following simpler, yet efficient method, proposed by Gusfield uses crossing cuts to produce equivalent flow trees. +Lets assume the vertices are 0-indexed for the next section +The algorithm is composed of the following steps: + +1. Create a (star) tree $T'$ on $n$ nodes, with node 0 at the center and nodes 1 through $n - 1$ at the leaves. +2. For $i$ from 1 to $n - 1$ do steps 3 and 4 +3. Compute the minimum cut $(X, Y)$ in $G$ between (leaf) node $i$ and its (unique) neighbor $t$ in $T'$. Label the edge $(i, t)$ in $T'$ with the capacity of the $(X, Y)$ cut. +4. For every node $j$ larger than $i$, if $j$ is a neighbor of $t$ and $j$ is on the $i$ side of $(X, Y)$, then modify $T'$ by disconnecting $j$ from $t$ and connecting $j$ to $i$. Note that each node $j$ larger than $i$ remains a leaf in $T'$ + +It is easy to see that at every iteration, node $i$ and all nodes larger than $i$ are leaves in $T'$, as required by the algorithm. + ## Complexity The algorithm total complexity is $\mathcal{O}(V*MaxFlow)$, wich means that the overall complexity depends on the algorithm that was choosen to find the maximum flow. @@ -21,6 +31,8 @@ This implementation considers the Gomory-Hu tree as a struct with methods: - The method *solve* returns a list that contains for each index $i$ the cost of the edge connecting $i$ and its parent, and the parent number. +- Note that the algorithm doesn't produce a *cut tree*, only an *equivalent flow tree*, so one cannot retrieve the two components of a cut from the tree $T'$. + ```{.cpp file=gomoryhu} struct gomory_hu { struct edg{ pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy