How to classify an edge that is not traversed in a depth-first search? - algorithm

I have an assignment that requires one to perform a depth-first search on a directed graph and to classify all edges of the graph. However, I'm confused as to how one would classify an edge that is not traversed during the course of the depth-first search, seeing as how these edges are classified during the course of a search.
Let me summarize a depth-first search on the above pictured graph.
First we go from 1 to 2. Then we pop 2 off the stack, because there is nowhere to go, so we're back at 1. Then we go from 1 to 3. Next we go from 3 to 4.
Ok, so assuming I got that part right, then all the edges traversed are Tree edges correct? So, how would one classify the edges between 3 to 2 and the edge from 4 to 3?

Your DFS should still traverse the edges from 3->2 and 4->3. They would be a cross edge and a back edge, respectively, IIRC.
You'll only actually push a node onto the stack the first time you see it, but when you do visit it, you look at all of its outgoing edges, whether their destinations have already been visited or not.

Related

Find maximal subgraph containing only nodes of degree 2 and 3

I'm trying to implement a (Unweighted) Feedback Vertex Set approximation algorithm from the following paper: FVS-Approximation-Paper. One of the steps of the algorithm (described on page 4) is to compute a maximal 2-3 subgraph of the input graph.
To be precise, a 2-3 graph is one that has only vertices of degree either 2 or 3.
By maximal we mean that that no set of edges or vertices of the original graph can be added to the maximal subgraph without violating the 2-3 condition.
The authors of the paper claim that the computation can be carried out by a "simple Depth First Search (DFS)" on the graph. However, this algorithm seems to elude me. How can the maximal subgraph be computed?
I think I managed to figure out something like what the authors intended. I wouldn't call it simple, though.
Let G be the graph and H be an initially empty 2-3 subgraph of G. The algorithm bears a family resemblance to a depth-first traversal, yet I wouldn't call it that. Starting from an arbitrary node, we walk around in the graph, pushing the steps onto a stack. Whenever we detect that the stack contains a path/cycle/sigma shape that would constitute a 2-3 super-graph of H, we move it from the stack to H and continue. When it's no longer possible to find such a shape, H is maximal, and we're done.
In more detail, the stack usually consists of a path having no nodes of degree 3 in H. The cursor is positioned at one end of the path. With each step, we examine the next edge incident to the end. If the only incident edge is the one by which we arrived, we delete it from both G and the stack and move the end back one. Otherwise we can possibly extend the path by some edge e. If e's other endpoint has degree 3 in H, we delete e from G and consider the next edge incident to the end. If e's other endpoint has degree 2 in H but is not currently on the stack, then we've anchored this end. If the other end is anchored too, then add the stack path to H and keep going. Otherwise, move the cursor to the other end of the stack, reversing the stack. The final case is if the stack loops back on itself. Then we can extract a path/cycle/sigma and keep going.
Typing this out on mobile, so sorry for the terse description. Maybe I'll find time to implement it.

Finding the heaviest edge in the graph that forms a cycle

Given an undirected graph, I want an algorithm (inO(|V|+|E|)) that will find me the heaviest edge in the graph that forms a cycle. For example, if my graph is as below, and I'll run DFS(A), then the heaviest edge in the graph will be BC.
(*) In this problem, I have at most 1 cycle.
I'm trying to write a modified DFS, that will return the desired heavy edge, but I'm having some trouble.
Because I have at most 1 cycle, I can save the edges in the cycle in an array, and find the maximum edge easily at the end of the run, but I think this answer seems a bit messy, and I'm sure there's a better recursive answer.
I think the easiest way to solve this is to use a union-find data structure (https://en.wikipedia.org/wiki/Disjoint-set_data_structure) in a manner similar to Kruskal's MST algorithm:
Put each vertex in its own set
Iterate through the edges in order of weight. For each edge, merge the sets of the adjacent vertices if they're not already in the same set.
Remember the last edge for which you found that its adjacent vertices were already in the same set. That's the one you're looking for.
This works because the last and heaviest edge that you visit in any cycle must already have its adjacent vertices connected by edges you visited earlier.
Use Tarjan's Strongly Connected Components algorithm.
Once you have split your graph into many strongly connected graphs assign a COMP_ID to each node which specifies the component ID to which this node belongs (This can be done with a small edit on the algorithm. Define a global integer value which starts at 1. Every time you pop nodes from the stack they all correspond to the same component, save the value of this variable to the COMP_ID of these nodes. When the pop loop ends increment the value of this integer by one).
Now, iterate over all the edges. You have 2 possibilities:
If this edge links two nodes from two different components, then this edge can't be the answer, since it can't possibly be a part of a cycle.
If this edge links two nodes from the same component, then this edge is a part of some cycle. All you have left to do now is to choose the maximum edge among all the edges of type 2.
The described approach runs in a total complexity of O(|V| + |E|) because every node and edge corresponds to at most one strongly connected component.
In the graph example you provided COMP_ID will be as follows:
COMP_ID[A] = 1
COMP_ID[B] = 2
COMP_ID[C] = 2
COMP_ID[D] = 2
Edge 10 connects COMP_ID 1 with COMP_ID 2, thus it can't be the answer. The answer is the maximum among edges {2, 5, 8} since they all connect COMP_ID 1 with it self, thus the answer is 8

Graphs - How to count the minimum number of "broken roads" necessary to go from v1 to v2?

Given a graph (undirected, no-weighted and all vertices are connected to eachother), I need to find the minimum number of "bad edges" I must visit to go from A to B. For example, if there's a graph with 5 vertices and the bad edges are: (0,1), (0,2), (0,3) and (0,4), to go from 0 to 4 I'll need to visit at least 1 bad edge. It could be straightfoward from 0 to 4 or from 0 to 1 and then 1 to 4. The length of the path doesn't matter at all. I'm trying a modified BFS to do the job but I'm not quite sure if this is the right way. My modification is instead of using a queue, use a list and when I find a bad edge, I put it into the back of the list, so I'll only visit this edge if really necessary, but found out that it won't minimize the number of bad edges. Any advices?
While it can indeed be solved by weighted shortest path, there is actually a more efficient (in terms of run time solutions).
First, define an auxillary graph G'=(V,E') where e is in E' iff e is "good". This step is linear in the size of the graph.
Now, you can find connected components in G' using DFS or BFS in O(|V|+|E|).
Next, all you have to do is "collapse" all nodes to a single node that represent them (this is also linear time), and add the "bad edges" (note that there is never a "good edge" that connects between two components, or they would have been in the same component).
Now, you can run BFS on the new graph, and the length of the path is the minimal number of nodes needed.
While this is significantly more complex to implement than a simple weighted shortest path, this solution offers O(|V|+|E|) (which in your graph is O(|E|)) run time, compared to O(|E|log|V|) of weighted shortest path.

Weighted graph traversal with skips

While I was in the shower today, I had a thought - How difficult would it be to write an algorithm to traverse a weighted di-graph and find the shortest path while allowed to skip a fixed number of edges s. I started thinking about even one skip, and for the brute force method it seems to multiply the problem by the number of edges in your graph, as you have to find the shortest path for each case where an edge is set to 0 cost and then compare across all graphs. I don't know if there are any algorithms that do this, but a cursory search of google didn't show any.
My first question would be for skipping the most costed edge(s), but it's also an interesting problem to examine having to find a path assuming you skip the least costed edge(s).
This is just to satisfy my curiosity, so no rush.
Thanks!
What follows is the logic of how to solve this problem. The way to solve this type of problem is to consider a graph composed of two copies of the original graph you want to traverse, which I'll describe how to create. For your sake, draw a small graph, and then draw it topologically sorted (which helps with the visualization, but is not necessary in the program.) Next, draw a copy of that graph a few inches above the original. You're in the bottom section of this graph when you have not yet used your skip, and you're in the top part when you have used your skip. Let's call the nodes in the bottom graph A1, A2, A3 ... and the nodes in the top graph B1, B2, B3 ... If, in your original graph, node 1 is connected to nodes 2, then your new graph has edges A1->A2, B1->B2, and a free connection, A1->B2 (with edge cost 0).
Consider the following original graph, where you start at the black node, and desire to end up at the blue node.
Your new graph will look like the following, where you again start at black and wish to go to the blue node.
At each location in the bottom half of the graph, you have not used your skip, and thus can either skip (moving to the top part of the graph) or can move normally, going to another node in the bottom graph.
You can then use any of the standard graph traversal algorithms.

A faster way to find out whether a cycle is formed if any node has at most 2 edges?

First of all, no homework.
Here is the problem:
An undirected unweighted graph has N nodes.
Any node can have at most 2 edges to different nodes.
I need to know whether at least a cycle is formed.
Input:
M pairs of integers, as edges.
There can be duplicates, like "2 3" and "3 2".
The data may be invalid, for example: "1 2" "1 3" "1 4". The program needs to detect this.
My approach (too slow):
0.1) A set for edges to detect duplicates. (C++ e.g.: std::set<int>)
0.2) A map for nodes to count how many edges from each node. (std::map<int,int>)
0.3) A list for links. A link is a set of connected nodes. (std::list<std::set<int> >)
1) Read in an edge, and change the edge to ascending order, e.g.: "3 2" -> "2 3".
2.1) If the edge has already be "drawn", skip and go to 1);
2.2) If either vertex has already got 2 edges, invalid!
2.3) Otherwise, check whether either of the nodes has already been in a link.
3.1) If neither, create a new link and add to the list.
3.2) If only one, add the single one to the link.
3.3) If both,
3.3.1) If in the same link, a cycle has been formed!
3.3.2) If not, merge two links.
Please recommend a faster algorithm, and the data structures for the algorithm. Thank you.
The standard algorithm for an undirected graph is to simply run a depth first search on it, keeping track of the nodes on the current path. If you run into a visited node, then you have a cycle.
Since each node has at most 2 incident edges, remove any nodes with 0 edges and then repeatedly remove any node that has only a single incident edge (and the corresponding edge). If you have a cycle you will reach a stage where there are no nodes that you can remove, but there will still be nodes left. If there is no cycle then you will terminate having removed all the nodes.
Edit: To deal with possibly invalid input and to be more explicit about the underlying data-structure.
As the data is read in build up a data-structure that is indexed by node ID and, for each indexed entry, contains a list of the nodes incident to that node. [I.e. as each edge is read in there are two entries to be made, one for each of the nodes.] As the data comes in remove duplicates and spot if any node is incident to too many edges. This is linear.
Keep a list of nodes with a single incident edge. At each step in the algorithm you pick any node from this list and, having removed the edge put the node to which it is linked in this list (if necessary). [If a node was already in the list you can either remove it or modify the previous step to just ignore any edges, taken from the list, that have no more incident edges.]
An edge is added at most once to the list and each iteration removes an edge from that list. Hence linear.
You can pick Prim's or Kruskal's algorithms for creating shortest spanning trees. Basically they both attempt to add edges of least weight to a new tree while not creating a circuit. You just have to modify the algorithm a tad so that in the event of a circuit creation, then you just break the procedure.
They both run as O(e log e) if I remember right (e: edges), but it'll likely be much faster as you can break of very early.

Resources