Skip to content
This repository has been archived by the owner on Nov 3, 2024. It is now read-only.

Commit

Permalink
Added Krushkal's Algorithm or Problem
Browse files Browse the repository at this point in the history
  • Loading branch information
darshkantaria committed Oct 27, 2024
1 parent f18a45b commit 53f47c9
Show file tree
Hide file tree
Showing 2 changed files with 172 additions and 0 deletions.
40 changes: 40 additions & 0 deletions Beginner Level 📁/Krushkal Algorithm/question.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Kruskal's Algorithm for Minimum Spanning Tree (MST)

## Problem Statement
Kruskal's algorithm is a **greedy algorithm** used to find the **Minimum Spanning Tree (MST)** of a connected, undirected graph. The MST is a subset of edges that connects all vertices with the minimum possible total edge weight and no cycles.

### Definitions
- **Graph**: Consists of vertices and weighted edges.
- **Minimum Spanning Tree (MST)**: A subset of edges that connects all vertices with minimum total edge weight.
- **Objective**: Find the MST for the graph.

## Input
- **V**: Number of vertices in the graph.
- **E**: List of edges, where each edge includes two vertices and a weight `(u, v, w)`.

## Output
- A list of edges that form the MST and the total minimum weight.

## Example
Given:
- Vertices: `V = {A, B, C, D}`
- Edges: `[(A, B, 1), (B, C, 2), (C, D, 3), (A, D, 4)]`

The MST would include edges `(A, B)`, `(B, C)`, and `(C, D)` with a total weight of **6**.

## Approach
1. **Sort the Edges**: Sort all edges in ascending order of their weights.
2. **Union-Find Structure**: Use the Union-Find data structure to detect cycles and help connect components.
3. **Add Edges Greedily**: Add edges to the MST in sorted order, skipping any that form a cycle.
4. **Stop Condition**: Stop once there are `V-1` edges in the MST.

### Steps:
1. Sort edges by weight.
2. Initialize MST as an empty set.
3. For each edge in sorted edges:
- If adding the edge doesn’t form a cycle, add it to the MST.
4. Output the MST and its total weight.

## Complexity
- **Time Complexity**: \(O(E \log E + E \log V)\), where \(E\) is the number of edges and \(V\) is the number of vertices.
- **Space Complexity**: \(O(V)\) for storing subsets in Union-Find.
132 changes: 132 additions & 0 deletions Beginner Level 📁/Krushkal Algorithm/solution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
class DisjointSet:
def __init__(self, vertices):
self.parent = {v: v for v in vertices} # Each vertex is its own parent (makes a set for each vertex)
self.rank = {v: 0 for v in vertices} # To keep track of the "depth" of trees for efficient union operations

def find_set(self, v):
if self.parent[v] != v:
self.parent[v] = self.find_set(self.parent[v]) # Path compression
return self.parent[v]

def union_set(self, u, v):
root1 = self.find_set(u)
root2 = self.find_set(v)

if root1 != root2:
if self.rank[root1] > self.rank[root2]:
self.parent[root2] = root1
else:
self.parent[root1] = root2
if self.rank[root1] == self.rank[root2]:
self.rank[root2] += 1

def kruskal(graph):
vertices = list(graph.keys()) # Get a list of all vertices from the graph
# If we remove "if u < v" condition then edges will be bidirectional means (a,b,6) & (b,a,6) both will appear
edges = [(u, v, w) for u in graph for v, w in graph[u].items() if u < v]
# Sort edges based on the given weights
edges.sort(key = lambda x: x[2]) # x = (u,v,w)

# Initialize the disjoint set with all vertices
ds = DisjointSet(vertices)

# Print the initial sets (only once)
print("Make sets:", end = " ")
for v in vertices:
print(f"{{ {v} }}", end = ", ")
print()

# For storing edges of minimum spanning tree
mst = []
for u, v, w in edges:
if ds.find_set(u) != ds.find_set(v): # Check if u and v belong to different sets
print(f"Selected edge: ({u}, {v}, {w})")

# Union operation and print the sets after union
ds.union_set(u, v)

# Find and print sets after edge selection
print("Make sets after selection:", end=" ")
sets = {}
for vertex in vertices:
root = ds.find_set(vertex) # Find the root of each vertex to know the current set
if root not in sets:
sets[root] = []
sets[root].append(vertex) # Group vertices by their root (which set they belong to)
for root, group in sets.items():
print(f"{{ {' '.join(sorted(group))} }}", end = ", ") # Print the current sets after the union operation
print()

mst.append((u, v, w)) # Add the selected edge to the MST

# Return list of selected edges
return mst

# Function to take user input for the graph
def input_graph():
# is_directed = input("Is the graph directed? (yes/no): ").lower() == "yes"
n = int(input("Enter the number of vertices: "))
m = int(input("Enter the number of edges: "))

graph = {}

print("Enter the edges in the format (u v w), where u and v are vertices, and w is the weight:")
for _ in range(m):
u, v, w = input().split()
w = int(w) # Convert the weight to an integer

if u not in graph:
graph[u] = {} # Initialize an empty dictionary for vertex u if it's not already in the graph
if v not in graph:
graph[v] = {} # Same for vertex v.

# Since it's an undirected graph, we add both u -> v and v -> u
# For Undirected graph
graph[u][v] = w
graph[v][u] = w

# Add only the directed edge u -> v
# For Directed graph
# graph[u][v] = w

return graph

# Take graph input from the user
graph = input_graph()

# Find the MST using Kruskal's algorithm
mst = kruskal(graph)

# Print the final MST
total_cost = 0
print("Minimum Spanning Tree:")
for u, v, w in mst:
print(f"({u}, {v}, {w})")
total_cost += w # Add the weight of each edge to the total cost

print(f"Total cost of MST: {total_cost}")
"""
graph = {
'a': {'b': 6, 'c': 4},
'b': {'a': 6, 'h': 10, 'c': 5, 'e': 14},
'c': {'a': 4, 'b': 5, 'f': 2, 'd': 9},
'd': {'c': 9},
'e': {'b': 14, 'h': 3},
'f': {'c': 2, 'g': 15, 'h': 8},
'g': {'f': 15},
'h': {'b': 10, 'e': 3, 'f': 8}
}
Points to Remember:-
● Time Complexity = O(nlogn) + O(n) = O(nlogn)
For sorting it takes O(nlogn) where n is the no of items
For 'for' loop it takes O(n)
● Space Complexity = O(V) + O(E) = O(V+E)
For storing edges of mst which would be 'V-1' it takes O(V)
For sorting edges it requires O(E)
● Both Krushkal's and Prim's algorithm is used only for undirected graph and for non-negative & zero weights.
● Edmonds' algorithm is used to find a minimum spanning tree (MST) in a directed graph.
"""

0 comments on commit 53f47c9

Please sign in to comment.