Horje
Prim's Algorithm in Python

Prim’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 the edges that connects all vertices in the graph with the minimum possible total edge weight.

Examples:

Input: Number of vertices: 5, Edges: [(0, 1, 2), (0, 3, 6), (1, 2, 3), (1, 3, 8), (1, 4, 5), (2, 4, 7), (3, 4, 9)]
Output: MST Edges: [(0, 1), (1, 2), (0, 3), (1, 4)], Total weight: 16
Explanation: The MST includes edges (0, 1), (1, 2), (0, 3), and (1, 4) with a total weight of 2 + 3 + 6 + 5 = 16.

Input: Number of vertices: 4, Edges: [(0, 1, 10), (0, 2, 6), (0, 3, 5), (1, 3, 15), (2, 3, 4)]
Output: MST Edges: [(2, 3), (0, 3), (0, 1)], Total weight: 19
Explanation: The MST includes edges (2, 3), (0, 3), and (0, 1) with a total weight of 4 + 5 + 10 = 19.

Approach:

To implement Prim’s algorithm in Python, follow these steps:

  1. Initialize:
    • Start with an arbitrary vertex (usually vertex 0) and mark it as part of the MST.
    • Use a priority queue (min-heap) to keep track of the edges connecting the MST to the remaining vertices, prioritized by their weights.
  2. Iterate:
    • Extract the minimum weight edge from the priority queue.
    • If the destination vertex of this edge is not already in the MST, add the edge to the MST and mark the vertex as part of the MST.
    • Add all edges from this newly added vertex to the priority queue, provided the destination vertices are not already in the MST.
  3. Repeat:
    • Continue the process until all vertices are included in the MST.

Below is the implementation of the algorithm:

Python
import heapq

# This class represents a directed graph using adjacency list representation


class Graph:
    def __init__(self, V):
        self.V = V
        self.adj = [[] for _ in range(V)]

    # Function to add an edge to the graph
    def add_edge(self, u, v, w):
        self.adj[u].append((v, w))
        self.adj[v].append((u, w))

    # Function to print MST using Prim's algorithm
    def prim_mst(self):
        pq = []  # Priority queue to store vertices that are being processed
        src = 0  # Taking vertex 0 as the source

        # Create a list for keys and initialize all keys as infinite (INF)
        key = [float('inf')] * self.V

        # To store the parent array which, in turn, stores MST
        parent = [-1] * self.V

        # To keep track of vertices included in MST
        in_mst = [False] * self.V

        # Insert source itself into the priority queue and initialize its key as 0
        heapq.heappush(pq, (0, src))
        key[src] = 0

        # Loop until the priority queue becomes empty
        while pq:
            # The first vertex in the pair is the minimum key vertex
            # Extract it from the priority queue
            # The vertex label is stored in the second of the pair
            u = heapq.heappop(pq)[1]

            # Different key values for the same vertex may exist in the priority queue.
            # The one with the least key value is always processed first.
            # Therefore, ignore the rest.
            if in_mst[u]:
                continue

            in_mst[u] = True  # Include the vertex in MST

            # Iterate through all adjacent vertices of a vertex
            for v, weight in self.adj[u]:
                # If v is not in MST and the weight of (u, v) is smaller than the current key of v
                if not in_mst[v] and key[v] > weight:
                    # Update the key of v
                    key[v] = weight
                    heapq.heappush(pq, (key[v], v))
                    parent[v] = u

        # Print edges of MST using the parent array
        for i in range(1, self.V):
            print(f"{parent[i]} - {i}")


# Driver program to test methods of the graph class
if __name__ == "__main__":
    # Create the graph given in the above figure
    V = 5
    g = Graph(V)

    (0, 1, 2), (0, 3, 6), (1, 2, 3), (1, 3, 8), (1, 4, 5), (2, 4, 7), (3, 4, 9)
    g.add_edge(0, 1, 2)
    g.add_edge(0, 3, 6)
    g.add_edge(1, 2, 3)
    g.add_edge(1, 3, 8)
    g.add_edge(1, 4, 5)
    g.add_edge(2, 4, 7)
    g.add_edge(3, 4, 9)

    g.prim_mst()

Output
0 - 1
1 - 2
0 - 3
1 - 4

Complexity Analysis:

  • Time Complexity:
    • Building the adjacency list takes O(E), where E is the number of edges.
    • Each edge is processed at most once, and operations on the priority queue (heap) take O(logV) time, where V is the number of vertices.
    • The overall time complexity is O((V+E)logV).
  • Space Complexity:
    • The space complexity is O(V+E) due to the adjacency list and the priority queue.



Reffered: https://www.geeksforgeeks.org


DSA

Related
Find Minimum Number of Operations to Make X and Y Equal Find Minimum Number of Operations to Make X and Y Equal
Rearrange Distant Barcodes Rearrange Distant Barcodes
Count K-Length Substrings With No Repeated Characters Count K-Length Substrings With No Repeated Characters
Maximum Flow Problem in Python Maximum Flow Problem in Python
Pancake Sorting in Python Pancake Sorting in Python

Type:
Geek
Category:
Coding
Sub Category:
Tutorial
Uploaded by:
Admin
Views:
14