How to detect a cycle in an Undirected Graph using Disjoint Sets? - algorithm

Algorithm:
For each edge (u, v) in the Adjacency list:
If u and v do not belong to the same set:
Union(u, v)
else:
return true // cycle detected
return false
Graph:
(1)-------(2)
Adjacency List:
[1] -> [2]
[2] -> [1]
Disjoint-Sets:
{{1}, {2}}
Iteration 1:
Edge e = (1, 2)
Union(1, 2)
Disjoint Sets = {{1, 2}}
Iteration 2:
Edge e = (2, 1)
Both 2 and 1 belong to the same set, so the algorithm detects a cycle.
It is obvious that the graph does not contain a cycle.
The algorithm works flawlessly for directed graphs. Please help me with this analysis.

A cycle must have distinct edges! In union find algorithm, you iterate through all the edges. You would need to filter out the duplicate edges from adjacency list. In your case, there is only one iteration so it would return false.

Related

Finding walk from s to t of length divisible by 3 in directed graph

From Jeff Erickson's lecture notes on graph algorithms, there is an exercise to check whether a walk between given vertexes s and t can be divisible by 3 in a directed graph.
What I thought is to use breadth-first search on the graph to get all paths from s to t. If the simple paths don't have lengths divisible by 3, run the algorithm again to check if there is a cycle between s and t where the length of cycle is not divisible by 3. However, I feel the method is really inefficient.
It would be great if you have any good suggestion about this question.
This kind of question can often be solved by changing the graph and applying a standard algorithm, instead of changing an algorithm.
In this case, we can create a new graph with three copies of each node, so e.g. if u is a node in the original graph, then the new graph has three corresponding nodes (u, 0), (u, 1) and (u, 2). For each edge u → v in the original graph, the new graph has three corresponding edges (u, 0) → (v, 1), (u, 1) → (v, 2), and (u, 2) → (v, 0).
Given a walk (n_0, r_0) → ... → (n_k, r_k) with k edges, we know that r[i+1] = r[i] + 1 (modulo 3), because all edges in the new graph satisfy that property. Therefore if r_0 = 0 then r_k = k (modulo 3).
It follows that (s, 0) has a walk to (t, 0) in the new graph if and only if s has a walk to t in the original graph using a multiple of 3 edges. So you can just apply a standard path-finding algorithm like BFS in the new graph to see if (t, 0) is reachable from (s, 0).
Note that if you have to actually implement this as code, it is not necessary to actually build the new graph as a data structure; it is an implicit graph.

Number of Paths in a Graph

I have an undirected, unweighted graph. Let us fix a vertex and find all distinct paths from that vertex which covers all vertices of the graph. The task is to find the number of possible such paths from every vertices.
Eg: Let us take a graph of 4 vertices [ 1, 2, 3, 4]. And the edges are (1,2), (2,3), (3,4), (4,2). Here answer is 4. The paths are 1>2>3>4, 1>2>4>3, 3>4>2>1, 4>3>2>1.
I have come with an algorithm which uses brute-force technique to find the number of possible such paths, initialized by each vertex.Eg:
For the above example:
From vertex 1 there is 2 such path;
From vertex 2 there is no such path;
From vertex 3 there is 1 such path;
From vertex 4 there is 1 such path;
So the answer is 2+1+1=4.
Is it possible to solve this problem in a better time complexity?
There's an O(2^n n^2)-time algorithm obtained by modifying the Held--Karp DP. The idea is, for each subset S of vertices paired with some endpoint t in S, compute the number of paths that visit exactly the vertices in S and end at t by summing, for each neighbor u of t that is in S, the count for visiting S - {t} and ending at u. As a base case, the singleton sets all have count 1. In Python 3:
import itertools
def count_hamilton_paths(graph): # graph is a dict of adjacency lists
vertices = frozenset(graph)
table = {(frozenset({t}), t): 1 for t in vertices}
for r in range(2, len(vertices) + 1):
for subset_tuple in itertools.combinations(vertices, r):
subset = frozenset(subset_tuple)
for t in subset:
subset_minus_t = subset - frozenset({t})
table[(subset, t)] = sum(table[(subset_minus_t, u)]
for u in graph[t]
if u in subset_minus_t)
return sum(table[(vertices, t)] for t in vertices)
print(count_hamilton_paths({1: {2}, 2: {1, 3, 4}, 3: {2, 4}, 4: {2, 3}}))

A function definition for directed acyclic graphs

Let's consider the following problem: For a directed acyclic graph G = (V,E) we define the function "levels" for each vertex u, as l(u) such that:
1. l(u)>=0 for every u
2. If there is a path from u to v (u -> v) then l(u)>l(v)
3. For each vertex u, l(u) is the minimum integer that satisfies both conditions 1 and 2.
The problem says:
a. Prove that for every DAG the above function is uniquely defined, i.e. it's the only function that satisfies conditions 1,2 and 3.
b. Find an O(|V| + |E|) algorithm that calculates this function for every vertex.
Here is a possible algorithm based on topological sort:
First we find the transpose of G which is G^T, defined as G^T = (V,E^T), where E^T={(u,v): (v,u) is in E} which takes O(|V|+|E|) in total if based on adjacency list implementation:
(O(|V|) for allocation and sum for all v in V of |Adj[v]| = O(|E|)). Topological sort takes Theta(|V|+|E|) since it includes a BFS and |V| insertions in list each of which take O(1).
TRANSPOSE(G){
Allocate |V| list pointers for G^T i.e. (Adj'[])
for(i = 1, i <= |V|, i++){
for every vertex v in Adj[i]{
add vertex i to Adj'[v]
}
}
}
L = TopSort(G)
a. Prove that for every DAG the above function is uniquely defined, i.e. it's the only function that satisfies conditions 1,2 and 3.
Maybe I am missing something, but this seems really obvious to me: if you define it as the minimum that satisfies those conditions, how can there be more than one?
b. Find an O(|V| + |E|) algorithm that calculates this function for every vertex.
I think your topological sort idea is correct (note that a topological sort is a BFS), but it should be performed on the transposed graph (reverse the direction of every edge). Then the first values in the topological sort get 0, the next get 1 etc. For example, for the transposed graph:
1 2 3
*-->*-->*
^
*-------|
1
I have numbered the nodes with their positions in the topological sort. You number the nodes by implementing the topological sort using a BFS. When you extract a node from your FIFO queue, you subtract 1 from the indegree of all of its reachable nodes. When that indegree becomes 0 you insert the node it became 0 for in the queue and you number it as exracted_node + 1. In my example, the nodes numbered 1 start with indegree 0. Then, the bottom-most 1 subtract one from the indegree of the node labeled 3, but that indegree will be 1, not zero, so we don't insert it in the queue. We insert 2 however because its indegree will become 0.
Pseudocode:
G = G^t
Q = a FIFO queue
push all nodes with indegree 0 in Q
set l(v) = 0 for all nodes with indegree 0
indegree(v) = how many edges are going into node v
while not Q.Empty():
x = Q.Pop()
for all nodes v reachable from x:
if indegree[v] > 0:
indegree[v] = indegree[v] - 1
if indegree[v] == 0:
Q.Push(v)
l[v] = l[x] + 1
You can also do it with a DFS that computes the value of each node once the recursion returns, as:
value(v) = 1 + max{value(c), c a child of v}
Note that the DFS is not dont on the transposed graph, because we'll let the recursion handle the traversal in topological sort order.
Let's say you have a topological sort of G. Then you can consider vertices in reversed order: if you have a u -> v edge, then v comes before u in ordering.
If you loop on the nodes with this order, then let l(u) = 0 if there is no outgoing edges and l(u) = 1 + max(l(v), for each v such that there is an edge (u, v)). This is optimal and give you an O(|V| + |E|) algorithm to solve this problem.
Proof is left as an exercise. :D

Decide whether there is a MST that contains some edges of 2 distinct edge sets

Let G = (V, E) be a weighted, connected and undirected graph. Let T1 and T2 be 2 different MST's. Suppose we can write E = (A1 U B U A2) such that:
B is the intersection of the edges of T1 and T2, and
A1 = T1 - B
A2 = T2 - B
Assuming that every MST T in G contains all the edges of B, find an algorithm that decides whether there is a MST T that contains at least one edge in A1 and at least one edge in A2.
Edit: I've dropped the part that was here. I think that it does more harm than good.
you should sort your edge that the red edge is prefer to blue edge for choose.then you can use any MST algorithm same as Prim's algorithm :
If a graph is empty then we are done immediately. Thus, we assume
otherwise. The algorithm starts with a tree consisting of a single
vertex, and continuously increases its size one edge at a time, until
it spans all vertices. Input: A non-empty connected weighted graph
with vertices V and edges E (the weights can be negative). Initialize:
Vnew = {x}, where x is an arbitrary node (starting point) from V, Enew
= {} Repeat until Vnew = V: Choose an edge {u, v} with minimal weight such that u is in Vnew and v is not (if there are multiple edges with
the same weight, any of them may be picked) Add v to Vnew, and {u, v}
to Enew Output: Vnew and Enew describe a minimal spanning tree

Finding a New Minimum Spanning Tree After a New Edge Was Added to The Graph

Let G = (V, E) be a weighted, connected and undirected graph and let T be a minimum spanning tree. Let e be any edge not in E (and has a weight W(e)).
Prove or disprove:
T U {e} is an edge set that contains a minimum spanning tree of G' = (V, E U {e}).
Well, it sounds true to me, so I decided to prove it but I just get stuck every time...
For example, if e is the new edge with minimum weight, who can promise us that the edges in T weren't chosen in a bad way that would prevent us from obtaining a new minimum weight without the 'help' of other edges in E - T ?
I would appreciate any help,
Thanks in advance.
Let [a(1), a(2), ..., a(n-1)] be a sequence of edges selected from E to construct MST of G by Kruskal's algorithm (in the order they were selected - weight(a(i)) <= weight(a(i + 1))).
Let's now consider how Kruskal's Algorithm behaves being given as input E' = E U {e}.
Let i = min{i: weight(e) < weight(a(i))}. Firstly algorithm decides to choose edges [a(1), ..., a(i - 1)] (e hasn't been processed yet, so it behaves the same). Then it need to decide on e - if e is dropped, solution for E' will be the same as for E. So let's suppose that first i edges selected by algorithm are [a(1), ..., a(i - 1), e] - I will call this new sequence a'. Algorithm continues - as long as its following selections (for j > i) satisfy a'(j) = a(j - 1) we are cool. There are two scenarios that break such great streak (let's say streak breaks at index k + 1):
1) Algorithm selects some edge e' that is not in T, and weight(e') < weight(a(k+1)). By now a' sequence is:
[a(1), ..., a(i-1), e, a(i), a(i+1), ..., a(k-1), a(k), e']
But if it was possible to append e' to this list it would be also possible to append it to [a(1), ..., a(k-1), a(k)]. But Kruskal's algorithm didn't do it when looking for MST for G. That leads to contradiction.
2) Algorithm politely selected:
[a(1), ..., a(i-1), e, a(i), a(i+1), ..., a(k-1), a(k)]
but decided to drop edge a(k+1). But if e was not present in the list algorithm would decide to append a(k+1). That means that in graph (V, {a(1), ..., a(k)}) edge a(k+1) would connect the same components as edge e. And that means that after considering by algorithm edge a(k + 1) in case of both G and G' the division into connected components (determined by set of selected edges) is the same. So after processing a(k+1) algorithm will proceed in the same way in both cases.
When ever a edge is add to a graph without adding a node , then that edge creates a cycle in minimum spanning tree of graph, cycle length may vary from 2 to n where n= no of nodes in graph.
T = Minimum spanning tree of G
Now to find the MST for (T + added edge) , we have to just remove one edge from that cycle .. so remove that edge which has maximum weight.
So T' always comes from T U {e}.
And if you are thinking that this doesn't prove that new MST will be an edge set of T U {e} then analyse Kruskal algorithim for for new graph. i.e. if e is of minimum weight it must have been selected for MST acc to Kruskal algorithim and same here if it is minimum it can not be removed from cycle.

Resources