Files
CS412-Applied-Algorithms/Railroad-Construction/connected_components.py

72 lines
2.4 KiB
Python
Raw Normal View History

# Implementation of the count-and-label
# connected component counting algorithm.
#
# Author: John Bowers
# Version: Mar 17, 2021
# March 2022 -- molloykp
# Changed code to label components starting a 0 (instead of 1)
# October 2023 -- molloykp
# Change code to accept new adj list/hash map structure
# Version of the iterative dfs that takes as input
# a list of labels, one per vertex, and a starting
# vertex v and uses iterative depth-first-search
# to label each vertex with a given currentLabel
#
# Parameters:
# * graph is an adjaceny list where vertices name/keys are stored
# in a dictionary. Each vertex has its own dictionary
# where the key is the edge endpoint and the value is the
# weight of the edge.
# * v is the vertex to DFS from
# * labels is an array of length V which is -1 if the vertex is unvisited
# * currentLabel is the label to set on every visited vertex
#
# labels is an out-parameter and will be modified destructively during the
# run of this operation.
#
def dfs_label(graph, v, labels, currentLabel):
bag = [v]
while bag: # while bag is not empty
u = bag.pop()
if labels[u] == -1:
labels[u] = currentLabel
for w in graph[u]:
bag.append(w)
# Counts the number of connected components in the graph
# and labels each vertex with its connected component index
#
# Parameters:
# * graph given as an adjaceny list/set structure with vertices 0..(n-1)
#
# Returns:
# count, labels
# where count is the number of connected components in the graph
# and labels is the labeling of each vertex's connected component
# starting from index 0
def count_and_label(graph):
labels = [-1 for _ in range(len(graph))] # Initially all labels are -1
count = -1
for v in range(len(graph)): # for each vertex
if labels[v] == -1: # if v is not visited
count += 1
dfs_label(graph, v, labels, count)
return count+1, labels
if __name__ == "__main__":
graph = {
0: {1:2}, # 0's neighbors
1: {0:2, 2:4, 3:1}, # 1's neighbors
2: {1:4, 3:5}, # 2's neighbors
3: {1:1, 2:5}, # 3's neighbors
4: {5:8}, # 4's neighbors
5: {4:8} # 5's neighbors
}
count, labels = count_and_label(graph)
print(f"Number of connected components: {count}")
print(f"Vertex labels: {labels}")