I'm attempting ch23 in CLRS on MSTs, here's a question:
Given a graph G and a minimum spanning tree T , suppose that we decrease the weight of one of the edges not in T . Give an algorithm for finding the minimum spanning tree in the modified graph.
A solution I found was to add this new changed edge in T, then exactly one simple cycle is created in T, traverse this cycle and delete the max-weight edge in this cycle, voila, the new updated MST is found!
My question is, how do I only traverse nodes on this simple-cycle? Since DFS/BFS traversals might go out of the cycle if I, say, start the traversal in T from one endpoint of this newly added edge in T.
One solution I could think of was to find the biconnected components in T after adding the new edge. Only one BCC will be found, which is this newly formed simple-cycle, then I can put in a special condition in my DFS code saying to only traverse edges/nodes in this BCC, and once a back-edge is found, stop the traversal.
Edit: graph G is connected and undirected btw
Your solution is basically good. To make it more formal you can use Tarjan's bridge-finding algorithm
This algorithm find the cut-edges (aka bridges) in the graph in linear time. Consider E' to be the cut-edges set. It is easy to prove that every edge in E' can not be on circle. So, E / E' are must be the cycle in the graph.
You can use hash-map or array build function to find the difference between your E and the cut-edges set
From here you can run simple for-loop to find the max weight edge which you want to remove.
Hope that help!
Related
I know the brute force approach for solving this problem which can be given as:
Iterate over all edges
Take a set(or list)(suppose s)
if adding an edge to s doesn't make a cycle then add edge to s
End if iteration is complete over all edges.
But I want an efficient solution(time+space both) for this problem.
So, Any help will be appreciated...........
Assuming that the graph is connected (otherwise no spanning tree exists): Beginning from some arbitrary vertex, perform depth-first search in the graph, recording for each vertex whether it has been visited already, and outputting every edge to an unvisited vertex that you come across. These edges comprise a spanning tree since they are cycle-free and visit every vertex.
This takes O(|V|+|E|) time and O(|V|) space.
First of all, I have to admit I'm not good at graph theory.
I have a weakly connected directed graph G=(V,E) where V is about 16 millions and E is about 180 millions.
For a given set S, which is a subset of V (size of S will be around 30), is it possible to find a weakly connected sub-graph G'=(V',E') where S is a subset of V' but try to keep the number of V' and E' as small as possible?
The graph G may change and I hope there's a way to find the sub-graph in real time. (When a process is writing into G, G will be locked, so don't worry about G get changed when your sub-graph calculation is still running.)
My current solution is find the shortest path for each pair of vertex in S and merge those paths to get the sub-graph. The result is OK but the running time is pretty expensive.
Is there a better way to solve this problem?
If you're happy with the results from your current approach, then it's certainly possible to do at least as well a lot faster:
Assign each vertex in S to a set in a disjoint set data structure: https://en.wikipedia.org/wiki/Disjoint-set_data_structure. Then:
Do a breadth-first-search of the graph, starting with S as the root set.
When you the search discovers a new vertex, remember its predecessor and assign it to the same set as its predecessor.
When you discover an edge that connects two sets, merge the sets and follow the predecessor links to add the connecting path to G'
Another way to think about doing exactly the same thing:
Sort all the edges in E according to their distance from S. You can use BFS discovery order for this
Use Kruskal's algorithm to generate a spanning tree for G, processing the edges in that order (https://en.wikipedia.org/wiki/Kruskal%27s_algorithm)
Pick a root in S, and remove any subtrees that don't contain a member of S. When you're done, every leaf will be in S.
This will not necessarily find the smallest possible subgraph, but it will minimize its maximum distance from S.
i have an undricted graph G=(V,E) and weight function w:E->R+. also, i have the MST T of G.
I have to build an algorithm that does the follow:
if we add a new edge e' that has the weight w(e') to E. suggest an algorithm that updates T in a way that it will be MST of the new graph G'=(V,EUe').
complexity: O(V).
what i suggested is:
1) Add e' to T. we get a new graph call it T' that include one cycle.
2) Run DFS on T' and mark every vertex that you visit. and in addition save
every vertex and every edge weight in stacks.
3) When we visit a vertex that we already visited we stop running.
4) and start withdrawing from the stack till we get to the vertex we stopped at.
5) while withdrawing we save the maximum edge weight we withdraw ed from the
stack.
6) if the maximum edge weight is bigger that w(e') we replace them.
7) otherwise we remain with the same T.
i hope it's clear.
i would be very grateful if anyone could till me if it works or give me other
solutions and suggestion.
Yes the solution you suggested is correct because a graph with the same number of edges and nodes (like T) consists of a simple cycle with trees rooted at some (maybe none) of the nodes of this cycle.
You need to delete exactly 1 edge from T such that the remaining graph is still connected. Obviously the best choice is to delete the largest edge. The only edges you can delete while keeping the graph connected are the ones in the cycle (the ones you are adding to the stack).
Another solution would be to find the bridges in the graph, then finding the maximum non-bridge edge and deleting it. However since this is a special graph the solution you mentioned would be much easier (the non-bridge edges are the ones on the cycle) .
I have a possible solution for the following question, but not sure if correct:
Assume we have already found a minimum spanning tree T for a weighted, undirected graph G = (V,E). We would like to be able to efficiently update T should G be altered slightly.
An edge is added to G to produce a new graph. Give an algorithm that uses T to find a minimum spanning tree for the new graph in O(|V|) time.
My algorithm:
for each vertex do
if smallest edge not in T then
replace this edge with existing edge in T
break
end if
end for
I do not have much experience in writing pseudocode, so my algorithm might be over-simplified or incorrect. Please correct me if I am wrong. Thanks!
Don't know if your algorithm is correct, but it doesn't seem O(|V|) at least, because getting the "smallest edge not in T" of a vertex cannot be done in O(1).
The most usual way to add an edge e=(u, v) into a MST T is:
Run a BFS in T from u to v to detect the edge with maximum value in that path. (O(|V|))
If that edge's weight is greater than the weight of the edge you're trying to add, remove that old edge and add the new one. Otherwise, do nothing, because the new edge would not improve the MST. (O(1)).
The rationale behind this solution is that simply adding the edge into T would create exactly one cycle, and to restore the MST property you have to remove the edge with maximum value from that cycle.
Yes, your algorithm seems to be correct. I would amend your pseudocode to clarify that "if smallest incident edge not in T then" so that your new algorithm is this:
for each vertex do
if smallest incident edge not in T then
replace this edge with existing edge in T
break
end if
end for
Proof by contradiction:
There exist two cases: the new edge is either in the MST or it isn't. For the case that it is: Suppose that the algorithm does not replace an edge in T. This must mean that all edges in T are smaller than other edges that are incident on the same vertex. This is a contradiction because that means the new edge is not in the MST of T.
The proof for the other case is a trivially similar proof by contradiction.
This is a question from Algorithm Design by Steven Skiena (for interview prep):
An articulation vertex of a graph G is a vertex whose deletion disconnects G. Let G be a graph with n vertices and m edges. Give a simple O(n + m) that finds a deletion order for the n vertices such that no deletion disconnects the graph.
This is what I thought:
Run DFS on the graph and keep updating each node's oldest reachable ancestor (based on which we decide if it's a bridge cut node, parent cute node or root cut node)
If we find a leaf node(vertex) or a node which is not an articulation vertex delete it.
At the end of DFS, we'd be left with all those nodes in graph which were found to be articulation vertices
The graph will remain connected as the articulation vertices are intact. I've tried it on a couple of graphs and it seems to work but it feels too simple for the book.
in 2 steps:
make the graph DAG using any traversal algorithm
do topology sort
each step finishes without going beyond O(m+n)
Assuming the graph is connected, then any random node reaches a subgraph whose spanning tree may be deleted in post-order without breaking the connectedness of the graph. Repeat in this manner until the graph is all gone.
Utilize DFS to track the exit time of each vertex;
Delete vertices in the order of recorded exit time;
If we always delete leaves of a tree one by one, rest of the tree remain connected. One particular way of doing this is to assign a pre-order number to each vertex as the graph is traversed using DFS or BFS. Sort the vertices in descending order (based on pre-order numbers). Remove vertices in that order from graph. Note that the leaves are always deleted first.