I am confused about this answer. Why can't DFS decide if there is a cycle in a directed graph while visiting each node and each edge at most once? Using the white, gray, black method, one should be able to find a cycle if there is a backward edge.
For an unconnected directed graph, why can't one do the following: run DFS from an arbitrary node v and visit as many nodes as v is connected to, then run DFS on another unvisited arbitrary node in the graph, if any, until all nodes are visited?
It seems to me that DFS should be able to find a cycle if it exists in at most o(|V|+|E|) time. Is this claim in the above mentioned answer wrong?
"It is possible to visit a node multiple times in a DFS without a
cycle existing"
Moreover, as this other answer suggest, if a cycle exists, DFS should find it after exploring a maximum of |V| edges, so the run time is really O(|V|).
What am I missing?
Update and conclusions:
Based on Pham Trung's comments, it looks like the "simple DFS" in that answer refers to a DFS starting from one node in a strongly connected graph. As I understand it, for a general case that the graph might be unconnected, the following statements should be true:
Using DFS and starting from an arbitrary unvisited node in an unconnected graph, it is true that each node might be visited more than once, but using white-gray-black coloring, a cycle -if exists - will be correctly found.
The run time of such a DFS algorithm is O(d.|V|+|E|), where d is the max in-degree among all nodes (i.e. the max time that we can visit each node using such DFS-based algorithm)
Moreover, as this other answer suggest, if after exploring O(|V|) edges, a cycle was not found, it does not exist. So the runtime is really O(|V|).
Imagine we have this simple graph with these edges:
1 -> 3
2 -> 3
1 ----->3
^
|
2--------
So, in our first dfs, we discover node 1 and 3. And, we continue to do dfs with node 2, now, we encounter node 3 again, but is this a cycle? obviously not.
One more example:
1 -> 3
1 -> 2
2 -> 3
1----->3
| ^
| |
| |
v |
2-------
So, starting with node 1, we visit node 3, back to node 2, and now, we encounter node 3 one more time, and, this case, it is not a cycle also.
As far as I understand the simple depth-first-search from Jay Conrod's answer means, a normal, original DFS (only checking for connected component). In the same answer, he also described how to modify simple DFS to find the existence of cycle, which is exactly the algorithm OP has cited. And right below, another answer also mentioned a lemma in the famous Introduction to algorithm book
A directed graph G is acyclic if and only if a depth-first search of G yields no back edges
In short, OP's understanding to detect cycle in directed graph is correct, it is just some complexities and shortcuts have lead to misunderstanding.
Related
I try to explain my problem better.
in input I have the number of nodes N and the number of edges P.
N represent the cities while P the water pipes.
So for example in input I have 4 and 2 {0,1,2,3,4} would be my graph
and the 2 represents me the already existing water pipes
since in the following lines of the file I will have the already
existing connections so since in this case I have the 2 for example in
the file I'll have 3-1 and 2-1. so at the beginning I will have a
graph with 5 vertices and an edge that goes from node 3 to node 1 and
another arc that goes from 2 to 1.
now I have to determine how many and which connections to make to
bring water to all the cities. so for example in this case a solution
could be 0-4,0-3,0-2.
NOTE 0 represents the dam basin.
I was thinking that this problem seems to me very similar to MST but the graph I have is oriented and not weighted so I cannot apply the Prim or Kruskal algorithm.
So since it doesn't make sense to apply MST maybe I could do this via a DFS or a BFS but I don't quite understand how.
I believe that if I do a dfs from the source then from node 0 and I see all the nodes that I have not been able to reach and I connect these nodes to the source I have the solution but I have not understood how to do it.
or would it be better to try to make l mst work on this type of graph then cloning it and adding weights = 1 to the arcs?
" I know I can't apply it for the type of graph I have"
How do you know this?
Unweighted. Make your graph weighted by applying a weight of 1 to every edge.
Undirected. Make your graph directed by replacing every edge with two directed edges, one going each way.
I'm doing some practice for an upcoming interview, and a practice question I found asks for an O(V+E) algorithm to tell if a graph is biconnected. This page from Princeton says that a graph is biconnected if it has no articulation vertices, where an articulation vertex is a vertex whose removal will increase the number of connected components (since a biconnected graph should have one connected component).
One common solution to this problem is to do DFS with additional tracking to see if any of the vertices are articulation vertices. This page says that a vertex is an articulation vertex if
V is a root node with at least 2 children
OR
V has a child that cannot reach an ancestor of V
However, the condition for root nodes doesn't make sense to me. Here is an example of a biconnected graph:
If we choose any of the nodes to be the root, they ALL have 2 or more children, so would be an articulation vertex thus making the graph not biconnected. This is a common algorithm for finding connected components, so assume I have misunderstood something. What do I actually need to check for the root node to see if a graph is biconnected?
You're supposed to do depth-first search, which means that the DFS tree always looks like
1 4
| |
2---3
because you can't explore the 1--4 link until you're done exploring everything that can be reached from 2 without going through 1, and you won't add 1--4 because it makes a cycle with the tree edges. No node in this tree has two children (1 is the root).
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.
Can Breadth First Search be used on Directed Acyclic Graph?
For example, you start with the root node (say it has 3 connected nodes, edges all pointing towards them from the root), following BFS, you visit the first connected node from the root following the directed edge, and you got to come back to the root node and visit the second connected node if it were an undirected graph, but you can't in the case of directed graph, so I assume BFS cannot be used on Directed Acyclic Graph?
Also,a line of nodes as such 1 -> 2 -> 3 -> 4 can be considered as a Directed Acyclic Graph, correct?
Thank
Short answer : Yes
Here is a video example. (This is no Adv, I don't know the guy)
Here is some written courses and examples.
To respond more precisely to your question, if there is no edge from a given node pointing to a root then you don't "have to" go back to the root, like others said in the comments.
The fact that the graph has cycles or not is not important because in BFS algorithms a node is supposed to be marked when you visit it. The mark is then used to not enqueue the node a second time (i.e to visit it only once), so the cycle is some how broken.
Just check the pseudo-code on Wikipedia.
An yes the "line of node" you mentioned is a DAG, but a very special one.
P.S : Sorry to dig up this question but I asked it to myself, searched the internet, saw it, keep searching and find some answers, so I thought it could help somebody else in the future.
1 -> 2 -> 3 -> 4
is a DAG
BFS means breath fast search. if u start bfs from a node u, every node which are reachable from u will be found but those nodes that are not reachable from u are not found.
example G (V,E ) a graph
v={1,2,3,4}
E={(1,2),(1,3),(4,1)}
if u run bfs from node 1 ,node 2 and 3 will be discovered
but 4 will be undiscovered
but if u run bfs from 4 every node will be discovered
So if u know the topological sorting of the DAG u can run bfs from the nodes in the topological order every node will be discovered and their level will be calculated correctly.
Before I start, yes this is a homework.
I would not have posted here if I haven't been trying as hard as I could to solve this one for the last 14 hours and got nowhere.
The problem is as follows:
I want to check whether I can delete an edge from a connected undirected graph without disconnecting it or not in O(V) time, not just linear.
What I have reached so far:
A cycle edge can be removed without disconnecting the graph, so I simply check if the graph has a cycle.
I have two methods that could be used, one is DFS and then checking if I have back edges; the other is by counting Vs and Es and checking if |E| = |V| - 1, if that's true then the graph is a tree and there's no node we can delete without disconnecting it.
Both of the previous approaches solve the problem, but both need O(|E|+|V|), and the book says there's a faster way(that's probably a greedy approach).
Can I get any hints, please?
EDIT:
More specifically, this is my question; given a connected graph G=(V,E), can I remove some edge e in E and have the resulting graph still be connected?
Any recursive traversal of the graph, marking nodes as they're visited and short-circuiting to return true if you ever run into a node that is already marked will do the trick. This takes O(|V|) to traverse the entire graph if there is no edge that can be removed, and less time if it stops early to return true.
edit
Yes, a recusive traversal of the entire graph requires O(|V|+|E|) time, but we only traverse the entire graph if there are no cycles -- in which case |E| = |V|-1 and that only takes O(|V|) time. If there is a cycle, we'll find it after traversing at most |V| edges (and visiting at most |V|+1 nodes), which likewise takes O(|V|) time.
Also, obviously when traversing from a node (other than the first), you don't consider the edge you used to get to the node, as that would cause you to immediately see an already visited node.
You list all edges E and take an edge and mark one by one the two end vertices visited. If during traversing we find that the two vertices have been visited previously by some edges and we can remove that edge.
We have to take edges at most |V| time to see whether this condition satisfy.
Worst case may go like this, each time we take an edge it will visit atleast new vertex. Then there are |V| vertices and we have to take |V| edges for that particular edge to be found.
Best case may be the one with |V| / 2 + 1 e
Have you heard of spanning trees? A connected graph with V-1 edges.
We can remove certain edges from a connected graph G (like the ones which are creating cycle) until we get a connected tree. Notice that question is not asking you to find a spanning tree.
Question is asking if you can remove one or more edges from graph without loosing connectivity. Simply count number of edges and break when count grows beyond V-1 because the graph has scope to remove more edges and become spanning tree. It can be done in O(V) times if the graph is given in adjacency list.
From what I'm reading, DFS without repetition is considered O(|V|), so if you take edge e, and let the two vertices it connects be u and v, if you run DFS from u, ignoring e, you can surmise that e is not a bridge if v is discovered, and given that DFS without repetition is O(|V|), then this would, I guess be considered O(|V|).