Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Add gomory-hu article#1308

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
igbrade wants to merge7 commits intocp-algorithms:main
base:main
Choose a base branch
Loading
fromigbrade:master
Open
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletionssrc/graph/gomory_hu.md
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
# Gomory Hu Tree
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Suggested change
#Gomory Hu Tree
---
tags:
- Original
---
#Gomory-Hu Tree


## Definition

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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Suggested change
Thegomory-hu tree of an undirected graph $G$ with capacitiesconsists ofa weighted tree thatcondenses information from all the*s-t cuts* for all s-t vertex pairs in thegraph. Naively, one must think that $O(|V|^2)$ flow computations are needed tobuild this data structure, but actually itcan be shown that only $|V| - 1$ flow computations are needed. Oncethe treeisconstructed, we can gettheminimum cut between two vertices*s* and*t* by querying the minimum weight edge in the unique*s-t* path.
TheGomory–Hu tree of an undirected graph $G$ with capacitiesisa weighted treesuchthatfor any pair of vertices $s$ and $t$, the weight of theminimum edge on the path between $s$ and $t$ is equal tothe value of the minimum cut between $s$ and $t$. Itcan be shown that only $|V| - 1$ flow computations are needed to constructthe tree, whichisan improvement overthenaive $O(|V|^2)$ algorithm of finding maximum flow between each pair of vertices.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Generally, it would be nice to explain why this tree is well-defined (e.g. why it always exists), if possible.


## 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.
Comment on lines +9 to +19
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

The way it is written now, it's very hard to seewhy the algorithm works this way. For example, crossing cuts are defined, but it is not explained why it is a property of interest that can be useful and helpful. It's not even clear how (non-)crossing curs are connected with the algorithm itself.

I assume the algorithm strives to maintain some kind of invariant that intermediate states provide a correct upper bound on the cut between any pair of vertices, and the bound is tight when the vertex is "finalised", but I don't see any natural explanation to why it's actually true?


## 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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Suggested change
The algorithm total complexity is $\mathcal{O}(V*MaxFlow)$, wich means that the overall complexity depends on the algorithm that waschoosen to find the maximum flow.
The algorithm total complexity is $\mathcal{O}(V)$ times the complexity of a single maximum flow call, wich means that the overall complexity depends on the algorithm that waschosen to find the maximum flow.


### Implementation
This implementation considers the Gomory-Hu tree as a struct with methods:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Suggested change
This implementation considers the Gomory-Hu tree as a struct with methods:
Below, we implement the Gomory-Hu tree as a`struct` with methods:


- 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 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'$.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

What is a cut tree? What is an equivalent flow tree? Neither are properly defined...


```{.cpp file=gomoryhu}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Was this implementation tested on any problem? If possible, it'd be nice to add some tests to the implementation, seehere.

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<edg> edgs;

void add_edge(int u, int v, int cap) { // the edges are already bidirectional
edgs.push_back({u, v, cap});
}

vector<int> 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<pair<ll, int>> solve(int n) {
vector<pair<ll, int>> 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)
1 change: 1 addition & 0 deletionssrc/navigation.md
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -190,6 +190,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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Suggested change
- [All-pairs minimum cut -Gomory Hu](graph/gomory_hu.md)
- [Gomory-Hu tree](graph/gomory_hu.md)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Please also add it to the list of new articles inREADME.

- Matchings and related problems
- [Bipartite Graph Check](graph/bipartite-check.md)
- [Kuhn's Algorithm - Maximum Bipartite Matching](graph/kuhn_maximum_bipartite_matching.md)
Expand Down

[8]ページ先頭

©2009-2025 Movatter.jp