1

I am trying to figure out how to print a Spanning Tree list from a given list of edges. For example, if I read in:

0 1

2 1

0 2

1 3

I want to print out a Spanning Tree list of:

[[1], [0,2,3], [1], [1]]

I know how to create an adjacency list using the code:

n = int(input("Enter number of vertices: "))
adjList = [[] for i in range(n)]
with open("graph.txt") as edges:
    for line in edges:
        line = line.replace("\n", "").split(" ")
        adjList[int(line[0])].append(int(line[1]))
        adjList[int(line[1])].append(int(line[0]))
    print(l)

But creating a Spanning Tree is a different story. Given that the Spanning Tree would be unweighted, I am not sure if I need to use some version of Prim's Algorithm here?

Any help is appreciated!

SumOne
  • 817
  • 3
  • 13
  • 24
  • I forgot to ask actually - are the edges directed? – Tagc Jan 16 '17 at 22:43
  • Pick a random vertex, `seen = set([random_vertex])`. Now choose an edge going from any of our already seen vertexes to any not yet seen vertex. Iterate (effectively Prims with no need to look for a minimum weighted edge) – donkopotamus Jan 16 '17 at 22:43
  • Hey thanks for the reply donkopotamus. I unfortunately do not know how to actually implement that, nor do I really even know how to implement Prim's algorithm in general. I'm not sure how I would reference the vertex? And how would I make sure a loop isn't formed? – theGreatWhatever Jan 17 '17 at 01:17
  • @Tagc no directed edges, just a basic unweighted graph – theGreatWhatever Jan 17 '17 at 01:17

1 Answers1

1

This implementation is based on the networkx package (documentation for it is here). Note that there's a few different spanning trees that I think you can get for that set of connections. This code will represent the spanning tree by its collection of edges, but I'll see if I can modify it to represent the tree the way you prefer.

import networkx as nx

def spanning_tree_from_edges(edges):
    graph = nx.Graph()

    for n1, n2 in edges:
        graph.add_edge(n1, n2)

    spanning_tree = nx.minimum_spanning_tree(graph)
    return spanning_tree

if __name__ == '__main__':
    edges = [(0, 1), (2, 1), (0, 2), (1, 3)]
    tree = spanning_tree_from_edges(edges)
    print(sorted(tree.edges()))

Output

[(0, 1), (0, 2), (1, 3)]

This alternative seems to represent the tree as the collection of node connections (i.e. in the format you want). Note that this collection is different because it's a different spanning tree to what you get:

if __name__ == '__main__':
    edges = [(0, 1), (2, 1), (0, 2), (1, 3)]
    tree = spanning_tree_from_edges(edges)
    print([list(nx.all_neighbors(tree, n)) for n in tree.nodes()])

Output

[[1, 2], [0, 3], [0], [1]]

Starting Graph

Generated Spanning Tree

Tagc
  • 8,736
  • 7
  • 61
  • 114
  • `networkx` is the most practical approach, but its worth noting that for large graphs we can do better ... `networkx` will be doing redundant weight sorting of edges – donkopotamus Jan 16 '17 at 22:50
  • Hey thanks Tagc, but I'm actually just trying to figure out how to represent a graph in the abstract sense, and am not worried about visual representation. – theGreatWhatever Jan 17 '17 at 01:18
  • @theGreatWhatever Didn't I do that though, in **Output**? The visual graphs below were just generated in a third-party tool to clarify what's happening. – Tagc Jan 17 '17 at 08:20
  • That's true, my bad. The issue is that I need to see the actual algorithm that generates the spanning tree list. Not sure where in NetworkX's documentation that, or if, it would be located. – theGreatWhatever Jan 22 '17 at 10:19
  • @theGreatWhatever The easiest way is just to debug my code and step into `nx.minimum_spanning_tree(graph)`. It says it uses Kruskal's. – Tagc Jan 22 '17 at 12:39