当前位置: 首页 > 知识库问答 >
问题:

创建“最小连通”有向无环图

孙佑运
2023-03-14

我在NetworkX中有一个有向无环简单图。

现在,对于每个边,该边都有一个“源”和一个“目标”。如果除了这个边之外,还有一条从“源”到“目标”的路径,那么我想删除这个边。

    null

>

  • 节点为:

    ['termsequence', 'maximumdegree', 'emptymultigraph', 'minimum', 'multiset', 'walk', 'nonemptymultigraph', 'euleriantrail', 'nonnullmultigraph', 'cycle', 'loop', 'abwalk', 'endvertices', 'simplegraph', 'vertex', 'multipletrails', 'edge', 'set', 'stroll', 'union', 'trailcondition', 'nullmultigraph', 'trivialmultigraph', 'sequence', 'multiplepaths', 'path', 'degreevertex', 'onedgesonvertices', 'nontrivialmultigraph', 'adjacentedges', 'adjacentvertices', 'simpleedge', 'maximum', 'multipleloops', 'length', 'circuit', 'class', 'euleriangraph', 'incident', 'minimumdegree', 'orderedpair', 'unique', 'closedwalk', 'multipleedges', 'pathcondition', 'multigraph', 'trail']
    

    边缘是:

    [('termsequence', 'endvertices'), ('emptymultigraph', 'nonemptymultigraph'), ('minimum', 'minimumdegree'), ('multiset', 'trailcondition'), ('multiset', 'pathcondition'), ('multiset', 'multigraph'), ('walk', 'length'), ('walk', 'closedwalk'), ('walk', 'abwalk'), ('walk', 'trail'), ('walk', 'endvertices'), ('euleriantrail', 'euleriangraph'), ('loop', 'simplegraph'), ('loop', 'degreevertex'), ('loop', 'simpleedge'), ('loop', 'multipleloops'), ('endvertices', 'abwalk'), ('vertex', 'adjacentvertices'), ('vertex', 'onedgesonvertices'), ('vertex', 'walk'), ('vertex', 'adjacentedges'), ('vertex', 'multipleedges'), ('vertex', 'edge'), ('vertex', 'multipleloops'), ('vertex', 'degreevertex'), ('vertex', 'incident'), ('edge', 'adjacentvertices'), ('edge', 'onedgesonvertices'), ('edge', 'multipleedges'), ('edge', 'simpleedge'), ('edge', 'adjacentedges'), ('edge', 'loop'), ('edge', 'trailcondition'), ('edge', 'pathcondition'), ('edge', 'walk'), ('edge', 'incident'), ('set', 'onedgesonvertices'), ('set', 'edge'), ('union', 'multiplepaths'), ('union', 'multipletrails'), ('trailcondition', 'trail'), ('nullmultigraph', 'nonnullmultigraph'), ('sequence', 'walk'), ('sequence', 'endvertices'), ('path', 'cycle'), ('path', 'multiplepaths'), ('degreevertex', 'maximumdegree'), ('degreevertex', 'minimumdegree'), ('onedgesonvertices', 'multigraph'), ('maximum', 'maximumdegree'), ('circuit', 'euleriangraph'), ('class', 'multiplepaths'), ('class', 'multipletrails'), ('incident', 'adjacentedges'), ('incident', 'degreevertex'), ('incident', 'onedgesonvertices'), ('orderedpair', 'multigraph'), ('closedwalk', 'circuit'), ('closedwalk', 'cycle'), ('closedwalk', 'stroll'), ('pathcondition', 'path'), ('multigraph', 'euleriangraph'), ('multigraph', 'nullmultigraph'), ('multigraph', 'trivialmultigraph'), ('multigraph', 'nontrivialmultigraph'), ('multigraph', 'emptymultigraph'), ('multigraph', 'euleriantrail'), ('multigraph', 'simplegraph'), ('trail', 'path'), ('trail', 'circuit'), ('trail', 'multipletrails')]
    
  • 共有1个答案

    龚安民
    2023-03-14

    是的。

    您希望使用all_simple_paths[documentation](它提供了两者之间所有简单路径的生成器)。一旦它找到第二个就退出,这样它就不会计算所有的。

    一旦定义了这一点,您希望查看每个边,如果从源到目标有多条路径,则删除该边。

    def multiple_paths(G,source,target):
        '''returns True if there are multiple_paths, False otherwise'''
        path_generator = nx.all_simple_paths(G, source=source, target=target)
        counter = 0
        for path in path_generator: #test to see if there are multiple paths
            counter += 1
            if counter >1:  
                break  #instead of breaking, could have return True
        if counter >1:  #counter == 2
            return True
        else:  #counter == 0 or 1
            return False
    
    import networkx as nx
    G=nx.DiGraph()
    G.add_edges_from([(0,1), (1,2), (1,3), (0,3), (2,3)])
    multiple_paths(G,0,1)
    > False
    multiple_paths(G,0,2) 
    > False
    multiple_paths(G,0,3)
    > True
    
    for edge in G.edges_iter():  #let's do what you're trying to do
        if multiple_paths(G, edge[0], edge[1]):
            G.remove_edge(edge[0],edge[1])
    
    G.edges()
    > [(0, 1), (1, 2), (2, 3)]
    
    import networkx as nx
    G=nx.DiGraph()
    G.add_edges_from([(0,1), (1,2), (1,3), (0,3), (2,3)])
    for edge in G.edges_iter():
        G.remove_edge(edge[0],edge[1])
        if not nx.has_path(G,edge[0],edge[1]):
            G.add_edge(edge[0],edge[1])
    
    G.edges()
    > [(0, 1), (1, 2), (2, 3)]
    

    不过,如果有任何边缘数据,您将需要小心,我不喜欢删除边缘然后再添加回来的可能性--这为一些难以发现的bug打开了机会。

     类似资料:
    • 考虑以下无向非循环图: 如果我们定义“根”为A和E,有没有算法可以确定产生的有向无环图?: 我考虑过从根开始尝试某种DFS或BFS,但我不确定如何处理“等待”的需要,以查看另一个根是否可能到达给定的节点。

    • 考虑一个不连通的有向图的例子,其中顶点和边其中顶点是孤立的。 根据这里的答案:(对强连通图的最小加法),保证这个图所需的最小边数结果是3。 如何找到将这些边添加到哪里,即图中一条边的起始点和终止点?

    • 我在这里要问的问题以前在堆栈溢出中已经被问过了。但我无法正确理解Skiminok发布的解决方案。 这是链接。 我尝试了上面链接上发布的解决方案,并给出了两个示例测试用例,但我无法得到正确的答案。 对于测试用例 1:: N=3 和 K=2 5 4 7 DAG将会是: 注:我构建上述DAG时考虑到: 设pi和pj是两个不同的问题。然后,我们将从pi到pj绘制一条有向边,当且仅当pj可以在pi之后的同一

    • 以下是完整的问题: null 我的两个问题是:(1)在最小化SCCs之间的边之前的算法是正确的吗?(2)如何使SCC之间的边最小化。 对于(2),我知道这相当于使DAG中的边数最小化。(将SCCs视为顶点)。但这似乎对我没有帮助。

    • 这是我的算法。 我做了一个。每次当我找到时,我都知道我得到了一个有向循环。 然后我将暂时沿着向后(直到我在循环中遍历所有顶点),并计算。 我的算法正确吗? 如果我的算法正确,时间复杂度是多少? 这个问题有没有更好的算法?