I wrote this pseudocode to create a spanning tree from a non oriented graph (G,V), where S is a stack and v is the vertex from which we want to start the computation:
PROCEDURE SPANNING-TREE(G,v)
S := {v}
while S is not empty
u := pop(S)
visit u
for each u' connected to u
if u' is not visited
s.push(u')
add-edge(u,u')
For some reason this algorithm is wrong. For example let's consider this simple non oriented graph:
If we start from the first vertex, we visit it and then we push 2 and 3 into the stack and we create two edges: (1,2) and (1,3). Then we visit 3, and since it is connected to 2 which hasn't been visited yet, we also create an edge (3,2), but this creates a cycle so the computed spanning tree is not a tree. Where'e the mistake? I cannot figure another way of computing a spanning tree in O(n).
You can just mark a vertex as visited when you push it to the stack, not when you pop it.
This would be my code. Here visited[] is a boolean array or hashtable
PROCEDURE SPANNING-TREE(G, v)
S := {v}
visited[v] := true
while S is not empty
u := pop(S)
for each u' connected to u
if u' is not visited
visited[u'] := true
s.push(u')
add-edge(u, u')
Related
Let G = (V,E) be a connected undirected graph. Let s in V be a vertex in the graph.
True/False: If v is a leaf in every spanning tree resulting from DFS(s), then v is a leaf in every spanning tree resulting from BFS(s) (v != s).
I assume that this one is True, and I think that because if v is a leaf in every DFS(s), that means v has no children on G graph, but I struggle to prove it.
I'd like to get some help.
Thanks a lot!
I am trying to design an algorithm where, given a connected weighted graph G = (V, E) and a subset of vertices U that is in V, will construct a minimum spanning tree such that all vertices in U are leaves (other vertices may also be leaves), or returns that no such tree exists (False).
This is all I got, adapting Prim's algorithm (fair warning, its really bad; don't even know if it works/is efficient or what data structures to use, I will accept literally any other correct algorithm instead):
Let x be an arbitrary node in G
Set S = {x}
While S != V:
Let (u,v) be the cheapest edge with u in S and v not in S
Add (u,v) to tree T if u is not in U, add v to S
If all u in U is in the tree T:
return T
Else:
return False
I also have a picture of what I think it would do to this graph I drew:
pic here
A proof that the algorithm is correct would also give me some peace of mind.
If all vertices u ∈ U are to be leaves in a solution, no u can be used in that solution to connect two other vertices. All vertices not in U must be connected by edges not incident to any u.
Remove U and all edges incident to U. Find the minimum spanning tree, then connect each u to the tree by the smallest-weighted edge available from those we removed.
Given undirected, connected graph, find all pairs of nodes (connected by an edge) whose deletion disconnects the graph.
No parallel edges and no edges connecting node to itself.
The problem seems similar to finding articulation points (or bridges) of a connected, undirected graph - yet with a twist, that we have to remove a pair of vertices connected by an edge (and all other edges connected to that pair).
This is a homework question. I've been trying to solve it, read about DFS and articulation points algorithms (that bookkeap depth and lowpoint of each node) - but none of these approaches help this particular problem. I've checked through Cormen's Intro to Algorithms, but no topic suggested itself as appropriate (granted, book does have 1500 pages).
While it's true that finding articulation point would also (most of the time) find such a pair, there are a lot of pairs that are not articulation points - consider a graph with 4-vertices,5-edges (square with a single diagonal): it has one such pair but no articulation points (nor bridges).
I'm lost. Help me, stack overflow, you are my only hope.
Rather straightforward, maybe not the most efficient:
Let the graph be G=(V,E) with V := {v_1, ..., v_n}. For each subset V' of V let G_V' be the node induced subgraph comprising the nodes V \ V'. Let further N>_v_i := {v_j in V : {v_i,v_j} in E and j > i} be the set of all neighbors of v_i in G with index greater than i. Finally, let c(G) be the set of connected components of a graph.
Compute the pairs as follows:
pairs = {}
for each v in V:
compute G_{v}
if G_{v} is unconnected:
for each v' in N>_v:
# Ensures that removal of v' does not render subgraph connected
# (Note comment by MkjG)
if |c(G_{v})| > 2 or {v'} not in c(G_{v}):
add {v,v'} to pairs
else:
for each v' in N>_v:
compute G_{v,v'}
if G_{v,v'} unconnected:
add {v,v'} to pairs
Connectivity can be checked via DFS or BFS in O(m+n). The runtime should hence be O(n * k * (m+n)), where k is the maximum degree of G.
Update to my previous answer based on the suggestion by #MkjG to use DFS for computing articulation points.
Let the graph be G=(V,E) with V := {v_1, ..., v_n}_. For each subset V' of V let G_V' be the node induced subgraph comprising the nodes V \ V'. For G connected, we call v in V an articulation point if G_{v} is unconnected. Let N_v be the set of neighbors of v in G.
Articulation points can be computed via DFS, read here for more information on the algorithm. In short:
compute a DFS tree T for some root node r in V
r is an articulation point, iff it has more than one child in T
any other node v in V is an articulation point, iff it has a child v' in T that satisfies the following condition: no node in the subtree T' of T rooted at v' has a back edge to an ancestor of v
Let the result of a DFS on graph G be a function c on the nodes v in V. c(v) is a subset of N_v, it holds v' in c(v) iff both of the following conditions are met:
v' is a child of v in T
no node in the subtree T' of T rooted at v' has a back edge to an ancestor of v
Note that for the root node r of T, c(r) is the set of all children of r. Function c can be computed in time O(n+m).
Compute the separator pairs as follows:
# performs DFS on G for some root node r
c = DFS(G,r)
# computes articulation points of G and corresponding number of components
aps = {}
compCounts = {}
for each v in V:
numComps = |c(v)|
if v != r:
++numComps
if numComps > 1:
add v to aps
compCounts[v] = numComps
# computes the set of all separator pairs containing at least on ap
S = {}
for each v in aps:
numComps = compCounts[v]
for each v' in N_v:
if numComps > 2:
# G_{v,v'} has at least two connected components
add {v,v'} to S
else:
# if v' is an isolated node in G_{v}, then G_{v,v'} is connected
if N_v' != {v}:
add {v,v'} to S
# computes remaining separator pairs
for each v in V \ aps:
compute G_{v}
# performs DFS on G_{v} for some root r_v != v
c_v = DFS(G_{v},r_v)
# adds separator pairs for articulation points of G_{v} in N_v
for each v' in N_v:
numComps = |c(v')|
if v' != r_v:
++numComps
if numComps > 1:
add{v,v'} to S
Runtime is in O(n * (n+m))
A set of k edges disconnecting a graph is called a k-cut. You are trying to enumerate all 2-cuts of a graph.
This paper describes an efficient algorithm to enumerate all cuts of a graph. It should be possible to adapt it to find all 2-cuts of a graph.
I am working on constructing an algorithm to compute G^2 of a directed graph that is a form of an adjacency list, where G^2 = (V,E'), where E' is defined as (u,v)∈E′ if there is a path of length 2 between u and v in G. I understand the question very well and have found an algorithm which I assume is correct, however the runtime of my algorithm is O(VE^2) where V is the number of vertices and E is the number of Edges of the graph. I was wondering how I could do this in O(VE) time in order to make it more efficient?
Here is the algorithm, I came up with:
for vertex in Vertices
for neighbor in Neighbors
for n in Neighbors
if(n!=neighbor)
then-> if(n.value==neighbor)
add this to a new adjacency list
break; // this means we have found a path of size 2 between vertex and neighbor
continue otherwise
The problem can be solved in time O(VE) using BFS(breadth first search). The thing about BFS, is that it traverses the graph level by level. Meaning that first it traverses all the vertices at a distance of 1 from the source vertex. Then it traverses all the vertices at a distance of 2 from the source vertex and so on. So we can take advantage of this fact and terminate our BFS, when we have reached vertices at a distance of 2.
Following is the pseudocode:
For each vertex v in V
{
Do a BFS with v as source vertex
{
For all vertices u at distance of 2 from v
add u to adjacency list of v
and terminate BFS
}
}
Since BFS takes time O(V + E) and we invoke this for every vertex, so total time is O(V(V + E)) = O(V^2 + VE) = O(VE) .Just remember to start with fresh data structures for every BFS traversal.
A source in a directed graph is a node that has no edges going into it. Give a linear-time algorithm
that takes as input a directed graph in adjacency list format, and outputs all of its sources.
solution:
Finding the sources of a directed graph.
We will keep an array in[u] which holds the indegree (number of incoming edges) of each node. For a
source, this value is zero.
function sources(G)
Input: Directed graph G = (V,E)
Output: A list of G's source nodes
for all u ∈ V : in[u] = 0
for all u ∈ V :
for all edges (u,w) ∈ E:
in[w] = in[w] + 1
L = empty linked list
for all u ∈ V :
if in[u] is 0: add u to L
return L
the thing i particularly do not understand about the code above is the innermost for loop in the first code block what exactly does in[w] = in[w]+1 mean? i think it means its counting the indegrees of each node, but how exactly it's doing that i cannot picture it, can someone please help me visualize this aspect
in[w] = in[w] + 1 increases the number of edges going into w.
Maybe an example will help:
Consider a simple graph:
a ---> b
The adjacency list representation is:
a: {b}
b: {}
Now the algorithm will loop through all vertices.
For a, it will loop over the edge (a,b) and increase b's count.
For b, there are no edges.
Now a's count is still zero, thus it is a source vertex.