1

我有这个硬件:

  1. 从文件中读取边缘列表
  2. 把它变成邻接表
  3. 输出图的未加权、无向生成树(我们可以假设起点在顶点 0)

我有问题 3. 正确输出。即,文件 1 应该输出[[1],[0,2,3],[1],[1]],我得到了[[1,2],[0,3],[0],[1]]这有点好,因为它们都是n=4从文件 1生成的树

但这是主要问题:我不知道我的代码有什么问题,对于文件 2:我得到:[[10], [], [10], [10], [], [], [], [], [], [], [0, 3, 2], [], []]

我的代码末尾的文件数据。(编辑:从tree=[]问题所在开始,其余没有问题)

这是我对这个问题的尝试:

import itertools

edge_i=[]
edge_j=[]
x = []
y = []
edgelist = []
n = int(input("Enter value for n:")) #input n for number of vertices
adjlist = [[] for i in range(n)] #create n sublists inside empty initial adjlist
data = [['0','1'],['2','1'],['0','2'],['1','3']]


for line in data: #for loop for appending into adjacency list the correct indices taken from out of the edgelist
    #(this line won't be needed when hardcoding input) line = line.replace("\n","").split(" ")
    for values in line:
        values_as_int = int(values)
        edgelist.append(values_as_int)



#set of vertices present in this file - pick out only n vertices
verticesset=set(edgelist)
listofusefulvertices=list(verticesset)[0:n]


P = list(itertools.permutations(listofusefulvertices,2))


x.append(edgelist[0::2])
y.append(edgelist[1::2])
x = sum(x,[])
y = sum(y,[])
dataint=zip(x,y)
datatuples=list(dataint)
outdata = set(datatuples)&set(P)
output=list(outdata)


for k in range(len(output)):
    edge_i.append(output[k][0])
    edge_i.append(output[k][1])
    edge_j.append(output[k][1])
    edge_j.append(output[k][0])

for i in range(len(edge_i)):
    u = edge_i[i]
    v = edge_j[i]
    adjlist[u].append(v)
print(adjlist)


tree = []
for vertexNum in range(len(listofusefulvertices)):
    tree.append([])
treeVertices = [0]*n
treeVertices[0]=1
for vertex in range(0,n): #(here the range in skeletal code from school used 1,n but it only worked for me when I used 0,n-1 or 0,n)
    if treeVertices[vertex] == 1:
        for adjVertex in adjlist[vertex]:
            if treeVertices[adjVertex] == 0:
                treeVertices[adjVertex]=1
                tree[adjVertex].append(vertex)
                tree[vertex].append(adjVertex)

print(tree)


#The data from files were: file 1: [['0','1'],['2','1'],['0','2'],['1','3']]
# file 2: [['10','2'],['7','4'],['11','3'],['1','12'],['6','8'],['10','3'],['4','9'],['5','7'],['8','12'],['2','11'],['1','6'],['0','10'],['7','2'],['12','5']]
4

2 回答 2

2

我没有浏览你所有的代码,你真的应该看看指导Minimal, complete, verifiable example

然而,将边列表转换为图是相当简单的,然后使用标准mst算法,例如 Prim 的:

def create_graph(edgelist):
    graph = {}
    for e1, e2 in edgelist:
        graph.setdefault(e1, []).append(e2)
        graph.setdefault(e2, []).append(e1)
    return graph

# Prim's
def mst(start, graph):
    closed = set()
    edges = []
    q = [(start, start)]
    while q:
        v1, v2 = q.pop()
        if v2 in closed:
            continue
        closed.add(v2)
        edges.append((v1, v2))
        for v in graph[v2]:
            if v in graph:
                q.append((v2, v))
    del edges[0]
    assert len(edges) == len(graph)-1
    return edges

>>> graph = create_graph([[10, 2], [7, 4], [11, 3], [1, 12], [6, 8], [10, 3], [4, 9], [5, 7], [8, 12], [2, 11], [1, 6], [0, 10], [7, 2], [12, 5]])
>>> min_gragh = create_graph(mst(0, graph))
>>> min_graph
{0: [10],
 1: [6],
 2: [11, 7],
 3: [10, 11],
 4: [7, 9],
 5: [7, 12],
 6: [8, 1],
 7: [2, 5, 4],
 8: [12, 6],
 9: [4],
 10: [0, 3],
 11: [3, 2],
 12: [5, 8]}
>>> [sorted(min_graph[k]) for k in sorted(min_graph)]
[[10], [6], [7, 11], [10, 11], [7, 9], [7, 12], [1, 8], [2, 4, 5], [6, 12], [4], [0, 3], [2, 3], [5, 8]]

一个图可能有多个有效的 MST,例如您的较小的edgelistproducts [[2], [2, 3], [0, 1], [1]],这也是一个有效的 MST,但与您的预期输出不同。

于 2017-03-27T23:30:20.570 回答
1

问题出在最后的主处理循环中。您使用节点 0 作为起始节点,但随后假设您的连接按数字顺序运行。您标记与节点 0 相邻的所有节点(仅节点 10),然后接下来占用节点 1。那还没有连接,所以你跳过它......但你永远不会回来。

这是我的低技术调试运行的代码和跟踪:

for vertex in range(0,n): #(here the range in skeletal code from school used 1,n but it only worked for me when I used 0,n-1 or 0,n)
    print ("Working on vertex", vertex, treeVertices[vertex] == 1)
    if treeVertices[vertex] == 1:
        for adjVertex in adjlist[vertex]:
            print ("  Adjacent vertex", adjVertex, treeVertices[adjVertex] == 0)
            if treeVertices[adjVertex] == 0:
                treeVertices[adjVertex]=1
                tree[adjVertex].append(vertex)
                tree[vertex].append(adjVertex)

print("Spanning tree", tree)

输出:

Adjacency list [[10], [12, 6], [11, 7, 10], [11, 10], [9, 7], [7, 12], [8, 1], [5, 4, 2], [6, 12], [4], [0, 3, 2], [2, 3], [1, 8, 5]]

Working on vertex 0 True
  Adjacent vertex 10 True
Working on vertex 1 False
Working on vertex 2 False
Working on vertex 3 False
Working on vertex 4 False
Working on vertex 5 False
Working on vertex 6 False
Working on vertex 7 False
Working on vertex 8 False
Working on vertex 9 False
Working on vertex 10 True
  Adjacent vertex 0 False
  Adjacent vertex 3 True
  Adjacent vertex 2 True
Working on vertex 11 False
Working on vertex 12 False
Spanning tree [[10], [], [10], [10], [], [], [], [], [], [], [0, 3, 2], [], []]

看到问题了吗?该算法假设如果您从可用节点移动到编号较高的节点,则查找生成树的流程将始终成功。由于这棵树需要多次“向下”移动,因此您无法全部完成。您从 0 开始,标记 10,然后跳过节点 1-9。当你达到 10 时,你添加了节点 2 和 3 ......但你永远不会回去扩展它们,这就是你得到的全部。

要获得所有这些,请执行以下两项操作之一:

  1. 将“未扩展”节点放在“待办事项”列表中,从 [0] 开始。您的顶部for循环更改为一段时间,直到该列表为空。
  2. 保留当前结构,但添加一个外部循环,该循环一直持续到所有节点都被标记,或者没有添加边(没有找到生成树)。

这会让你转向解决方案吗?

于 2017-03-28T01:02:02.377 回答