Concept of Tarjan's bridge-finding algorithm - algorithm

I was doning a problem of finding a bridge in a undirected connected graph, I looked up wikipedia for Tarjan's algorithm. Here is what it writes
Tarjan's bridge-finding algorithm
The first linear time algorithm for finding the bridges in a graph was described by
Robert Tarjan in 1974. It performs the following steps:
Find a spanning forest of G
Create a rooted forest F from the spanning forest
Traverse the forest F in preorder and number the nodes. Parent nodes in the forest now have lower numbers than child nodes.
For each node v in preorder (denoting each node using its preorder number), do:
Compute the number of forest descendants ND(v) for this node, by adding one to the sum of its children's descendants.
Compute L(v), the lowest preorder label reachable from v by a path for which all but the last edge stays within
the subtree rooted at v. This is the minimum of the set
consisting of the preorder label of v, of the values of
L(w) at child nodes of v and of the preorder
labels of nodes reachable from v by edges that do not
belong to F.
Similarly, compute H(v), the highest preorder label reachable by a path for which all but the last edge stays within the
subtree rooted at v. This is the maximum of the set
consisting of the preorder label of v, of the values of
H(w) at child nodes of v and of the preorder
labels of nodes reachable from v by edges that do not
belong to F.
For each node w with parent node v, if L(w) = w and H(w) < w + ND(w) then the edge
from v to w is a bridge.
I wonder whether I understand the previous steps wrong, since in my opinion, I think that L(w) = w is never gonna happen except at the root. Where in other cases, L(w) should be at least smaller than the father of w.
Source

The English description of L and H is slightly wrong -- they should exclude paths that contain the parent edge, or else it's as if there are parallel edges between each pair of adjacent nodes, hence no bridges. The algorithm for computing L and H correctly iterates over children only.

Related

How to describe an algorithm to decide whether T is a depth-first spanning tree rooted at s?

Let's Suppose we have a connected graph G, a start vertex s, and a spanning tree T of G and G is undirected. How can I describe an algorithm to decide if T is a depth-first spanning tree rooted at s or not?
All DFS trees T for an undirected graph G have the following property:
{u, v} is an edge in G if and only if u is an ancestor of v in T or v is an ancestor of u in T.
To see why, assume without loss of generality that u is visited before v in the DFS. When building the DFS tree node for u, we will either (1) choose to visit node v as a neighbor of u, making node u a parent of node v, or (2) starting at node u we will visit some other neighbor z, and in recursively exploring z we will visit v, in which case u is a parent of z and z is an ancestor of v.
Moreover, we can make a stronger claim: any tree meeting the above criterion is a DFS tree for some DFS tree of G. Here’s how to see this. Start with the root node of T and look at its children. Given any two subtrees of the root, none of the nodes in those subtrees can be adjacent to one another in G, since otherwise by the above property one of those nodes would have to be an ancestor of the other. Therefore, each subtree consists of a set of nodes that are all reachable from one another via paths that only involve the nodes within that subtree. We can then recursively assemble one possible DFS ordering by starting at the root, recursively building DFS trees for the subgraphs represented by the subtrees in any order we’d like, and gluing those DFS orders together.
With this observation in mind, we can check very quickly with a second DFS whether T can be a DFS tree rooted at s, tracking which nodes have been visited as the DFS runs. After all children of a node v have been processed, check whether all the neighbors of v in graph G have been visited. If so, great! If not, it means that some neighbor of v is neither an ancestor nor a descendant, and the tree isn’t a DFS tree. If this process terminated without finding any violations, the process itself traces out a DFS of G using the edges of T, so T is definitely a valid DFS tree.
This algorithm runs in time O(m + n), which is as fast as possible here. After all, if you don’t look at all the nodes or edges of G, you can’t be sure whether the tree is a valid DFS tree because you can’t check the core property listed above.

Specific Graph and need to more Creative solution

Directed Graph (|V|=a, |E|=b) is given.
each vertexes has specific weight. we want for each vertex (1..a) find a vertex with maximum weight that can be reachable from that vertex.
Update 1: one nice answer is prepare by #Paul in O(b + a log a). but I
search for O(a + b) algorithms, if any?
Is there any different efficient or fastest any other ways for doing it?
Yes, it's possible to modify Tarjan's SCC algorithm to solve this problem in linear time.
Tarjan's algorithm uses two node fields to drive its SCC finding logic: index, which represents the order in which the algorithm discovers the nodes; and lowlink, the minimum index reachable by a sequence of tree arcs followed by a back arc. As part of the same depth-first traversal, we can compute another field, maxweight, which has one of two meanings:
For a node not yet included in a finished SCC, it represents the maximum weight reachable by a sequence of tree arcs, optionally followed by a cross arc to another SCC and then any subsequent path.
For nodes in a finished SCC, it represents the maximum weight reachable.
The logic for computing maxweight is as follows. If we discover an arc from v to a new node w, then vw is a tree arc, so we compute w.maxweight recursively and update v.maxweight = max(v.maxweight, w.maxweight). If w is on the stack, then we do nothing, because vw is a back arc and not included in the definition of maxweight. Otherwise, vw is a cross arc, and we do the same update that we would have done for a tree arc, just without the recursive call.
When Tarjan's algorithm identifies an SCC, it's because it has a node r with r.lowlink == r.index. Since r is the depth-first search root of this SCC, its value of maxweight is correct for the whole SCC. Instead of recording each node in the SCC, we simply update its maxweight to r.maxweight.
Sort all nodes by weight in decreasing order and create the graph g' with all edges in E reversed (i.e. if there's an edge a -> b in g, there's an edge b -> a in g'). In this graph you can now propagate the maximum-value by simple DFS. Do this iteratively for all nodes and terminate when a maximum-weight has already been assigned.
As pseudocode:
dfs_assign_weight_reachable(node, weight):
if node.max_weight_reachable >= weight:
return
node.max_weight_reachable = weight
for n = neighbor of node:
dfs_assign_weight_reachable(n, weight)
g' = g with all edges reversed
nodes = nodes from g' sorted descendingly by weight
assign max_weight_reachable = -inf to each node in nodes
for node in nodes:
dfs_assign_weight_reachable(node, node.weight)
UPDATE:
The tight bound is O(b + a log a). a log a is caused by the sorting step. And each edge gets visited once during the reversal step and once during the assigning maximum weights, giving the second term in the max-expression.
Acknowledgement:
I'd like to thank #SerialLazer for the time invested in a discussion about the time-complexity of the above algorithm and helping me figure out the correct bound.

How to prove there always exists a minimax path completely on the MST

A minimax path in an undirected graph is a path between two vertices v, w that minimizes the maximum weight of the edges on the path.
Let T be the minimum spanning tree of a given graph G=(V,E). How can I prove that, for any pair of vertices v, w in V, there always exists a minimax path between v and w that is completely on T.
I have tried to assume there is no minimax path completely on T, but I don't know how to get a contradiction.
Assume there exists a minimax path P between vertices u and v that is not completely on the minimum spanning tree T.
This means there is an edge A(p, q) in P that is not in T.
Let Q be the path in T from p to q.
Let B be an edge with the greatest weight in Q (in the imaged graph the length of the edge represents its weight):
T is marked in green
P = (u,p,q,v)
There are now 2 conditions to consider:
weight(B) > weight(A): In that case T is not a minimum spanning tree. If you would remove B from T and add A instead, you would still have a spanning tree, but its total weight would have decreased. As this is a contradiction (T is given as being a minimum spanning tree), the only possibility left is:
weight(B) <= weight(A): In that case you could remove A from P and add the edges from Q to it instead, and it would still be a minimax path, as we did not include an edge with a greater weight than that was already on that path before.
Note that this replacement will make the minimax path longer, but that is not an issue. There can be several paths between two vertices that all minimise the maximum edge weight -- there is no requirement that the minimax path be the shortest of those.
For every edge A on a minimax path that is not in T, an edge replacement can be done as described in point 2, thereby creating a minimax path that will be completely on T.
Suppose that there is a minimax path outside the minimum spanning tree that does better than the path on the minimum spanning tree. Remove the most costly edge on the minimum spanning tree path from the tree, splitting the graph into two connected components. You can get from one component to another using the minimax path. As you go along this path, there must be one edge that leaves one of the components and enters the other component. Add this edge to the minimum spanning tree. The graph is now connected again and the total cost of the minimum spanning tree has reduced, because every edge on the minimax path had a cost less than that of the most costly edge on the minimum spanning tree. So we have a contradiction and no such minimax path can exist.

Find spanning tree that specific v has k degrees

can someone explain for me how to solve it i know that we should use DFS but i cant understand what we do after that.
input : undirected graph G and specific v that belong to the G
output : spanning tree that v has k degree
I will suggest the following way.
Here I assume G is connected.
First remove v from the graph, find spanning tree for each of the remaining component.
Now you may have a single spanning tree or a forest depending on the graph, you can add back v and use the edges to connecting v and each of the spanning tree.
Then you will have a spanning tree of G, and there will be three cases.
case 1: degree v > k, in this case, the task is impossible
case 2: degree v = k, you have the answer.
case 3: degree v < k, then you just add unused edges of v. Each time you add an edge you will create a cycle, then you can just choose an edge which does not touch v and remove it.
You keep adding edges until you have your answer or all edges run out.
However, I cannot think of a fast way to query a cycle besides doing bfs/dfs.
Update: There is a faster way for case 3 by Matt, after connecting v to k appropriate neighbors, use Kruskal's or Prim's algorithm to fill in the rest of the spanning tree, starting with the edges from v that you already have.
Here is an algorithm that I am providing, but its pretty much brute force.
Condition for such tree to exist: if the degree of v < k, then such tree does not exist.
else follow the algorithm as:
Pick k vertices out of all the adjacent vertices of v,
1.mark all adjacent vertices of v as VISITED.
2.From each of those adjacent vertices , call DFS and the spanning tree grows.
3.After all DFS is complete,if all vertices of graph G are marked VISITED, then we
have our spanning tree, if a single vertex or more are left UNVISITED, then the
4.pick another set of k vertices.
if v has X as degree and X > k, then step 4 has to be repeated XCk(X choose k) times in the worst case.
We can think this way too:
For the given vertex v among all the neighbor v_i s.t. (v,v_i) in E(G) pick k edges with the smallest weights w(v,v_i), we need O(d*lg(d)) time where deg(v)=d >= k. Add these edges to the spanning tree edge set S. We have to add these edges to S anyway to ensure that the constraint holds.
Remove vertex v from the graph G along with all edges incident on v. Now run Prim/Kruskal on the graph G \ {v} starting with the edge set S, the algorithm itself will add edges ensuring the acyclic and minimum properties. This will run in O(m*lg(n)).
Assuming d small step 1 & 2 runs in O(m*lg(n)).

Design an algorithm to detect cycle in graph G

What would the following algorithm look like:
a linear-time algorithm which, given an undirected graph G, and a particular edge e in it, determines whether G has a cycle containing e
I have following Idea:
for each v that belongs to V,
if v is a descendant of e and (e,v) has not been traversed then check following:
if we visited e before v and left v before we left e then
the graph contains cycle
I am not sure if this is your homework so I'll just give a little hint - use the properties of breadth-first search tree (with root in any of the two vertices of the edge e), its subtrees which are determined by neighbors of the root and the edges between those subtrees.
Per comingstorm's hint, an undirected edge is itself a cycle. A<->B back and forth as many times as you like.

Resources