8

我正在尝试解决 Udacity 上的一个问题,如下所述:

# Find Eulerian Tour
#
# Write a function that takes in a graph
# represented as a list of tuples
# and return a list of nodes that
# you would follow on an Eulerian Tour
#
# For example, if the input graph was
# [(1, 2), (2, 3), (3, 1)]
# A possible Eulerian tour would be [1, 2, 3, 1]

我想出了以下解决方案,虽然不像某些递归算法那样优雅,但在我的测试用例中似乎确实有效。

def find_eulerian_tour(graph):
    tour = []

    start_vertex = graph[0][0]
    tour.append(start_vertex)

    while len(graph) > 0:
        current_vertex = tour[len(tour) - 1]
        for edge in graph:
            if current_vertex in edge:
                if edge[0] == current_vertex:
                    current_vertex = edge[1]
                elif edge[1] == current_vertex:
                    current_vertex = edge[0]
                else:
                    # Edit to account for case no tour is possible
                    return False

                graph.remove(edge)
                tour.append(current_vertex)
                break
    return tour

graph = [(1, 2), (2, 3), (3, 1)]
print find_eulerian_tour(graph)

>> [1, 2, 3, 1]

然而,当我提交这个时,我被评分员拒绝了。我做错了什么?我看不到任何错误。

4

10 回答 10

8

这是您的算法失败的有效案例:

graph = [(1, 2), (2, 3), (3, 1), (3, 4), (4, 3)]

使用 的力量print找出graph和发生了什么current_vertex

另一个提示:else向下移动,使其属于for并且在for循环不中断时执行。像现在这样,它永远无法执行。在那次更正之后,算法当然仍然失败。

当然,算法仍然失败。

当然,算法仍然失败。

请不要评论说代码不起作用。它没有。即使下面的代码符合 OP 的想法,该算法仍然失败。关键是要表明 OP 的算法是错误的,而 OP 无法确定。为此,需要正确实现 OP 算法(见下文)。错误算法的正确实现仍然不是正确的解决方案。

我很抱歉写了所有这些冗长的解释使这个答案变得更糟,但是人们继续抱怨代码不起作用(当然,重点是表明它是错误的)。他们也对这个答案投了反对票,可能是因为他们希望能够复制代码作为解决方案。但这不是重点,重点是向 OP 表明他的算法存在错误。

下面的代码没有找到欧拉之旅。寻找其他地方复制代码以传递你的assingments!

def find_eulerian_tour(graph):
    tour = []

    current_vertex = graph[0][0]
    tour.append(current_vertex)

    while len(graph) > 0:
        print(graph, current_vertex)
        for edge in graph:
            if current_vertex in edge:
                if edge[0] == current_vertex:
                    current_vertex = edge[1]
                else:
                    current_vertex = edge[0]

                graph.remove(edge)
                tour.append(current_vertex)
                break
        else:
            # Edit to account for case no tour is possible
            return False
    return tour

graph = [(1, 2), (2, 3), (3, 1), (3, 4), (4, 3)]
print(find_eulerian_tour(graph))

输出:

[(1, 2), (2, 3), (3, 1), (3, 4), (4, 3)] 1
[(2, 3), (3, 1), (3, 4), (4, 3)] 2
[(3, 1), (3, 4), (4, 3)] 3
[(3, 4), (4, 3)] 1
False
于 2012-09-17T11:12:47.200 回答
4

我也在同一个讲座中,WolframH 的回答对我不起作用。这是我的解决方案(已被评分者接受):

将所有可能的东西推next node入一个堆(search),然后在记录时搜索它们中的每一个。

def next_node(edge, current):
    return edge[0] if current == edge[1] else edge[1]

def remove_edge(raw_list, discard):
    return [item for item in raw_list if item != discard]

def find_eulerian_tour(graph):
    search = [[[], graph[0][0], graph]]
    while search:
        path, node, unexplore = search.pop()
        path += [node]

        if not unexplore:
            return path

        for edge in unexplore:
            if node in edge:
                search += [[path, next_node(edge, node), remove_edge(unexplore, edge)]]

if __name__ == '__main__':
    graph = [(1, 2), (2, 3), (3, 1), (3, 4), (4, 3)]
    print find_eulerian_tour(graph)

[1、3、4、3、2、1]

于 2016-07-15T23:56:06.210 回答
2

这是您的算法无法处理的情况:4 个顶点上的完整图。在那里坚持一个print tour,你得到:

>>> cg4 = [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)]
>>> find_eulerian_tour(cg4)
[0]
[0, 1]
[0, 1, 2]
[0, 1, 2, 0]
[0, 1, 2, 0, 3]
[0, 1, 2, 0, 3, 1]
[0, 1, 2, 0, 3, 1]
[0, 1, 2, 0, 3, 1]
[etc.]

我会让你找到你的方法的问题——你可以很容易地用谷歌搜索一个完整的实现,所以既然你没有,我假设你想要自己弄清楚它的乐趣。:^)

编辑:

嗯。我承认我认为这只是一开始就错过的失败案例。无论如何,@WolframH 击败了我更新的示例,但您也可以查看5个顶点的完整图,您的代码在其中给出

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

并错过了边缘 (2,3)、(2,4) 和 (3,4)。

于 2012-09-16T15:36:21.457 回答
2

这个问题比使用简单递归的上述解决方案更容易解决。

def find_eulerian_tour(graph):
    tour=[]
    find_tour(graph[0][0],graph,tour)
    return tour
def find_tour(u,E,tour): 
  for (a,b) in E:
    if a==u:
        E.remove((a,b))
        find_tour(b,E,tour)
    elif b==u:
        E.remove((a,b))
        find_tour(a,E,tour)
  tour.insert(0,u)

此代码适用于任何输入的元组列表并返回游览列表。如果有的话,请发送建议和更改。谢谢@WolframH:如果图中存在任何循环并且输入元组只是为了使您的代码失败,您的代码将不起作用。

于 2013-11-08T18:47:12.330 回答
2

我在 Udacity 上同样的课程。在从 Wikipedia 阅读 Hierholzer 算法后,我实现了它。这是算法的链接https://en.wikipedia.org/wiki/Eulerian_path

下面是我的代码。毫无疑问,它被评分者接受了(在做了一些 Python3 到 Python2 的更改之后)。:)

#!/usr/bin/env python3
# Find Eulerian Tour
#
# Write a program that takes in a graph
# represented as a list of tuples
# and return a list of nodes that
# you would follow on an Eulerian Tour
#
# For example, if the input graph was
# [(1, 2), (2, 3), (3, 1)]
# A possible Eulerian tour would be [1, 2, 3, 1]

def get_a_tour():
    '''This function returns a possible tour in the current graph and removes the edges included in that tour, from the graph.'''
    global graph

    nodes_degree = {}       # Creating a {node: degree} dictionary for current graph.
    for edge in graph:
        a, b = edge[0], edge[1]
        nodes_degree[a] = nodes_degree.get(a, 0) + 1
        nodes_degree[b] = nodes_degree.get(b, 0) + 1

    tour =[]        # Finding a tour in the current graph.
    loop = enumerate(nodes_degree)
    while True:
        try:
            l = loop.__next__()
            index = l[0]
            node = l[1]
            degree = nodes_degree[node]
            try:
                if (tour[-1], node) in graph or (node, tour[-1]) in graph:
                    tour.append(node)
                    try:
                        graph.remove((tour[-2], tour[-1]))
                        nodes_degree[tour[-1]] -= 1     # Updating degree of nodes in the graph, not required but for the sake of completeness.
                        nodes_degree[tour[-2]] -= 1     # Can also be used to check the correctness of program. In the end all degrees must zero.
                    except ValueError:
                        graph.remove((tour[-1], tour[-2]))
                        nodes_degree[tour[-1]] -= 1
                        nodes_degree[tour[-2]] -= 1
            except IndexError:
                tour.append(node)
        except StopIteration:
            loop = enumerate(nodes_degree)

        if len(tour) > 2:
            if tour[0] == tour[-1]:
                return tour

def get_eulerian_tour():
    '''This function returns a Eulerian Tour for the input graph.'''
    global graph
    tour = get_a_tour()

    if graph:   # If stuck at the beginning, finding additional tour in the graph.
        loop = enumerate(tour[: -1])
        l = loop.__next__()
        i = l[0]
        node = l[1]
        try:
            while True:
                if node in list(zip(*graph))[0] or node in list(zip(*graph))[1]:
                    t = get_a_tour()    # Retreivng the additional tour
                    j = t.index(node)
                    tour = tour[ : i] + t[j:-1] + t[ :j+1] + tour[i+1: ]        # Joining the two tours.
                    if not graph:       # Found Eulerian Tour
                        return tour     # Returning the Eulerian Tour
                    loop = enumerate(tour[: -1])        # Still stuck? Looping back to search for another tour.
                l = loop.__next__()
                i = l[0]
                node = l[1]
        except StopIteration:   # Oops! seems like the vertices in the current tour cannot connect to rest of the edges in the graph.
            print("Your graph doesn't seem to be connected")
            exit()
    else:       # Found the Eulerian Tour in the very first call. Lucky Enough!
        return tour

# Sample inputs
# graph = [(1, 2), (1, 3), (2, 3), (2, 4), (2, 6), (3, 4), (3, 5), (4, 5), (4, 6)]
# graph = [(1, 2), (1, 3), (2, 3)]
# graph = [(1, 2), (1, 3), (2, 3), (2, 4), (2, 6), (3, 4), (3, 5), (4, 5), (4, 6), (9, 10), (10, 11), (11, 9)]
# graph = [(1, 2), (1, 3), (2, 3), (2, 4), (2, 6), (3, 4), (3, 5), (4, 5), (4, 6), (2, 7), (7, 8), (8, 2)]
# graph = [(1, 2), (1, 3), (2, 3), (2, 4), (2, 6), (3, 4), (3, 5), (4, 5), (4, 6), (1, 5), (5, 6), (1, 6)]
# graph = [(1, 2), (2, 3), (3, 1), (3, 4), (4, 3)]
# graph = [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)]
# graph = [(2, 6), (4, 2), (5, 4), (6, 5), (6, 8), (7, 9), (8, 7), (9, 6)]

# creating a {node: degree} dictionary
nodes_degree = {}
for edge in graph:
    a, b = edge[0], edge[1]
    nodes_degree[a] = nodes_degree.get(a, 0) + 1
    nodes_degree[b] = nodes_degree.get(b, 0) + 1

#checking degree
degrees = nodes_degree.values() # remember it return a view
for degree in degrees:
    if degree % 2:
        print("Your graph have one or more nodes with odd degrees. Hence an Eulerian Tour is impossible.")
        exit()

#finding Eulerian Tour
tour = get_eulerian_tour()
print(tour)

希望这可以帮助。

于 2015-07-30T15:51:28.430 回答
1

这是Gregor Ulm 网页中的原始代码,它可以工作。

def find_eulerian_tour(graph):

def freqencies():
    # save all nodes of edges to my_list
    # e.g. [3,4,5,1,2,2,3,5]
    my_list = [x for (x, y) in graph]
    # get the max num of nodes-->create a list
    # set all to 0
    # for i in range(5) = 0 1 2 3 4
    # so range("5" +1) means
    # len=6, result=[0,0,0,0,0,0]
    # so that the index = the number itself
    result = [0 for i in range(max(my_list) + 1)]
    # nodes in my_list, increment
    # e.g. [0,1,2,2,1,2] 
    # 3appears 2times.
    for i in my_list:
        result[i] += 1
    return result
    # this is Frequencies of each nodes.

def find_node(tour):
    for i in tour:
        if freq[i] != 0:
            return i
    return -1

def helper(tour, next):
    find_path(tour, next)
    u = find_node(tour)
    while sum(freq) != 0:     
        sub = find_path([], u)
        # get the sub_path
        # add them together
        # when draw to u, turn to sub, and then come back to go on the original tour path
        # [:a], start to a; [a+1:] a+1 to end
        tour = tour[:tour.index(u)] + sub + tour[tour.index(u) + 1:]  
        u = find_node(tour)
    return tour

def find_path(tour, next):
    for (x, y) in graph:
        if x == next:
            # from "double-graph"
            # pop out the current one and its respondent one
            # actually it means we delete this edge
            current = graph.pop(graph.index((x,y)))
            graph.pop(graph.index((current[1], current[0])))
            # now add this "next" node into the tour
            tour.append(current[0])
            # decrement in frequency
            freq[current[0]] -= 1
            freq[current[1]] -= 1
            return find_path(tour, current[1])
    # if this "next" node is not connected to any other nodes
    # single one
    tour.append(next)
    return tour             

# in graph, all edges get reversed one and be added to graph
# can call it "double-graph"  
# it helps to calculate the frequency in find_path
# actually we can regard frequency as degrees for each node       
graph += [(y, x) for (x, y) in graph]
freq = freqencies()   
# set graph[0][0] as starting point
return helper([], graph[0][0])

graph = [(1, 2), (2, 3), (3, 1)]
print find_eulerian_tour(graph)
于 2017-01-07T21:40:56.403 回答
0

尽管代码对于无向图失败,但在有向图上运行得非常好。从 Udacity 的角度来看,它仍然不能解决手头的问题,但可以被视为相同的低版本。请不要介意使用不当的 Python,因为我还是该语言的新手。


底部添加了两个相当复杂的测试场景。


initialNode = ''
nglength = 0
in_graphLength = 0
normalizedGraph = list()
path = []
node_dict = {}
mod_flag = ''
  
def find_eulerian_tour(graph):
    global in_graphLength
    in_graphLength = len(graph)
    graph = normalize_graph(graph,[],-1,len(graph))
    print (path)
    return path
def normalize_graph(graph,nG,remNode,length):
    counter = 0
    global path
    global initialNode
    global in_graphLength
    global nglength
    global normalizedGraph
    localGraph = list()
    path = []
    pathList = []
    if(remNode != -1):
        normalizedGraph = nG
    baseNode = 0
    if(len(normalizedGraph) != 0):
        ini1, ini2 = normalizedGraph[0]
        initialNode = ini1
        a1,b1 = normalizedGraph[len(normalizedGraph) - 1]
        baseNode = b1
        if(remNode != -2):
            graph.pop(remNode)
    if(remNode == -1):
        a,b = graph[0]
        baseNode = b
        normalizedGraph.append(graph[0])
        initialNode = a
        nglength = 1
        graph.pop(0)
    i = 0
    if(len(graph) != 0):
        for n1, n2 in graph:
            i = i + 1
            if(n1 == baseNode):
                localGraph = graph[:]
                if(isJunction((n1,n2),localGraph, nglength)):
                    graph.pop(i-1)
                    graph.append((n1,n2))
                    normalize_graph(graph, normalizedGraph, -2,in_graphLength)
                    break
                else:
                    normalizedGraph.append((n1, n2))
                    nglength = nglength + 1
                    normalize_graph(graph, normalizedGraph, i - 1,in_graphLength)
                    break

    else:
        if( counter == 0):
            counter = counter + 1
            a0, b0 = normalizedGraph[0]
            for n1, n2 in normalizedGraph:
                path.append(n1)
            path.append(a0)
            path = path
            return path

def isJunction((n1,n2), graph, nglength):
    global node_dict
    count = 0
    if(len(graph) > 1):
        for a1, a2 in graph:
            if (n1 == a1):
                count = count + 1
        if (count > 1):
            if(str(n1) not in node_dict):
                key = str(n1)
                node_dict[key] = count
            else:
                return handle_degree(n1)
            return modification_needed((n1, n2), graph, nglength)
        else:
            return False
    else:
        return False

def handle_degree(n1):
    global node_dict
    key = str(n1)
    if(node_dict.get(key) == 2):
        return False

def modification_needed((n1,n2),graph, tmplength):
    i = 0
    global mod_flag
    if( n2 == initialNode):
        return True
    if(len(graph) > 1):
        for b1, b2 in graph:
            if(n2 == b1):
                i = i + 1
                tmplength = tmplength + 1
                if (b1,b2) in normalizedGraph:
                    mod_flag = True
                    continue
                if(tmplength < in_graphLength and b2 == initialNode):
                    mod_flag = True
                    continue
                else:
                    graph.pop(i-1)
                    modification_needed((b1,b2),graph,tmplength)
    return mod_flag


#find_eulerian_tour([(1,2),(2,6),(7,2),(6,1),(2,3),(3,5),(3,4),(4,5),(5,7),(7,3),(5,6),(6,7)])
#find_eulerian_tour([(0,4),(1,0),(4,2),(4,8),(2,5),(9,5),(8,9),(5,4),(5,1),(7,1),(3,7),(1,6),(6,3)])
于 2016-10-28T21:58:11.260 回答
0

您可以模仿 BFS 算法的行为并搭载它。

注意:我没有尝试使用链表编写答案,因为链表需要定义 2 个类(一个定义节点及其行为,一个定义整个链表及其行为)。但是,为了提高(追加)​​和(删除)行为的效率,您应该使用链表而不是数组:

def find_eulerian_tour(graph):
    nodes = set()

    for i in graph:
        if not i[0] in nodes:
            nodes.add(i[0])
        if not i[1] in nodes:
            nodes.add(i[1])

    tour = []
    tempstack = []
    graphtemp = []

    current_vertex = graph[0][0]
    tour.append(current_vertex)
    tempstack.append(current_vertex)
    last_edge = ()
    count = 0

    while len(set(tempstack)) + 1 < len(nodes) or (count == 0 or tour[0] != tour[len(tour) - 1]):
        count += 1
        flag = False
        for edge in graph:
           if current_vertex in edge and edge != last_edge:
                if current_vertex == edge[0]:
                    current_vertex = edge[1]
                else:
                    current_vertex = edge[0]
                last_edge = edge
                graphtemp.append(edge)
                graph.remove(edge)
                tour.append(current_vertex)
                tempstack.append(current_vertex)
                flag = True
                break

        if flag == False:
            tour.remove(current_vertex)
            current_vertex = tempstack[0]
            tempstack.remove(tempstack[0])
            graph.append(graphtemp[0])
            graphtemp.remove(graphtemp[0])


    return tour


print find_eulerian_tour([(1,2), (2,3), (3,1)])
print(find_eulerian_tour([(0, 1), (1, 5), (1, 7), (4, 5), (4, 8), (1, 6), (3, 7), (5, 9), (2, 4), (0, 4), (2, 5), (3, 6), (8, 9)]))
print(find_eulerian_tour([(1, 13), (1, 6), (6, 11), (3, 13), (8, 13), (0, 6), (8, 9),(5, 9), (2, 6), (6, 10), (7, 9), (1, 12), (4, 12), (5, 14), (0, 1),  (2, 3), (4, 11), (6, 9), (7, 14),  (10, 13)]))
print(find_eulerian_tour([(8, 16), (8, 18), (16, 17), (18, 19), (3, 17), (13, 17), (5, 13),(3, 4), (0, 18), (3, 14), (11, 14), (1, 8), (1, 9), (4, 12), (2, 19),(1, 10), (7, 9), (13, 15), (6, 12), (0, 1), (2, 11), (3, 18), (5, 6), (7, 15), (8, 13), (10, 17)]))
于 2017-07-17T08:27:18.277 回答
0

该解决方案针对O(V+E)复杂度进行了优化,即图中边和顶点的数量呈线性

对于那些直接希望查看代码的人:https ://github.com/cubohan/py-algos/blob/master/eulerian_tour.py

请注意,代码主要违反了可读性和 DRY 设计,但在阅读说明后,您可以轻松制作自己的版本。

# eulerian_tour.py by cubohan
# circa 2017
#
# Problem statement: Given a list of edges, output a list of vertices followed in an eulerian tour
#
# complexity analysis: O(E + V) LINEAR


def find_eulerian_tour(graph):
    edges = graph
    graph = {}
    degree = {}
    start = edges[0][0]
    count_e = 0
    for e in edges:
        if not e[0] in graph:
            graph[e[0]] = {}
        if not e[0] in degree:
            degree[e[0]] = 0
        if not e[1] in graph:
            graph[e[1]] = {}
        if not e[1] in degree:
            degree[e[1]] = 0
        graph[e[0]][e[1]] = 1
        graph[e[1]][e[0]] = 1
        degree[e[0]] += 1
        degree[e[1]] += 1
        count_e += 1
    max_d = 0
    this_ = 0
    for v, d in degree.items():
        if not d%2 == 0:
            # Eulerian tour not possible as odd degree found!
            return False 
        if d>max_d:
            this_ = v
            max_d = d
    visited_e = {}
    def is_visited(i, j):
        key = str(sorted([i,j]))
        if key in visited_e:
            return True
        else:
            visited_e[key] = True
            return False
    start = this_
    route = [start]
    indexof = {}
    indexof[start] = 0
    while count_e>0:
        flag = False
        for to_v in graph[this_]:
            if not is_visited(to_v, this_):
                route.append([to_v])
                indexof[to_v] = len(route)-1
                degree[to_v] -= 1
                if degree[to_v] == 0:
                    del degree[to_v]
                degree[this_] -= 1
                if degree[this_] == 0:
                    del degree[this_]
                this_ = to_v
                flag = True
                count_e -= 1
                break
        if not flag:
            break
    for key, v in degree.items():
        if v <=0:
            continue
        try:
            ind = indexof[key]
        except Exception as e:
            continue
        this_ = key
        while count_e>0:
            flag = False
            for to_v in graph[this_]:
                if not is_visited(to_v, this_):
                    route[ind].append(to_v)
                    degree[to_v] -= 1
                    degree[this_] -= 1
                    this_ = to_v
                    flag = True
                    count_e -= 1
                    break
            if not flag:
                break
    route_ref = []
    for r in route:
        if type(r) == list:
            for _r in r:
                route_ref.append(_r)
        else:
            route_ref.append(r)
    return route_ref

if __name__ == "__main__":
    print find_eulerian_tour([(0, 1), (1, 5), (1, 7), (4, 5),(4, 8), (1, 6), (3, 7), (5, 9),(2, 4), (0, 4), (2, 5), (3, 6), (8, 9)])

**首先问题可以分为这些子任务:**

  1. 将图形构建成比边列表更友好的结构,以便于处理,即(邻接列表)

  2. 找到每个顶点的度数以首先检查是否可能进行欧拉之旅(是否只有偶数度?另外,将这些值存储在以顶点为键的字典中 => 以供以后使用)

  3. 构建欧拉之旅

我的解决方案背后的概念很简单。

  1. 您选择度数最高的顶点作为起点并将其设置为当前顶点。(注意:您在计算每个顶点的度数时同时完成此操作。您将所有这些度数存储在字典中。)

  2. 您在路由列表中插入当前顶点,这是您的答案(注意:还要在路由列表中创建一个顶点字典及其索引。这将在稍后使用。)

  3. 如果尚未访问,则访问当前顶点的第一条边。(注意:维护了访问边的字典,该字典的键是构成边的一对顶点的排序元组。访问边后,通过将其插入字典来标记它已访问。)

  4. 您维护当前顶点和访问顶点的剩余度数(这将在以后证明很有用)(注意:您只需在每次选择边之前从生成的度数中减去 1)

  5. 您将当前顶点切换到您决定访问的边的另一端的顶点。

  6. 重复步骤 2-5,直到在当前顶点中找不到未访问的边。(注意:这意味着您已经返回到起始顶点)

现在考虑这一点:请注意,任何未访问的边/顶点将构成主图中的子图,这些子图具有与主图相同的属性,即欧拉之旅可以从子图中的任何顶点开始和结束于同一顶点。

因此,可以通过在这些子图中进行欧拉之旅来访问所有未访问的边。您只需要将这些子之旅与第一个之旅合并。

下一个:

  1. 当且仅当此顶点的缩减度不为零时,您循环遍历图形的所有顶点并在与主游览列出的相同过程中构建子游览

  2. 这些游览将与之前计算的路线列表合并的方式是,您将考虑从路线列表中开始子游览的顶点的位置替换为子游览输出列表,然后展平此路线列表

我们还没有完成!上面有什么问题?

当您得到一个尚未访问且不在路线列表中的非零度顶点时会发生什么?!

警告: 这是一个例外情况。

您可能会遇到以前未访问过的顶点,因此它们不会出现在主路由列表中。

循环时忽略这些!您已经访问过的具有非零缩减度的顶点之一是保证在您将从这些顶点开始创建的子游览中引导这些顶点。

这怎么可能??!!

从代码链接中给出的测试用例中绘制图表,您就会明白。追踪您的算法在流程的每一步都在做什么。画出来!图像的理解复杂度为 log(N),单词的复杂度为 O(n2)。

啊,请注意,只有当输入列表中的所有边都形成一个图而不是两个单独的不相交图时,这个保证才成立。

于 2017-01-15T11:05:33.417 回答
0

如果我们这样做呢?(刚刚检查过,它通过了 udacity 测试!!)

import itertools
def create_tour(alist):
    return list(itertools.permutations(alist,2))
于 2018-03-16T09:12:19.347 回答