简体   繁体   English

为无向图中的所有节点存储 dist(node, start) 的算法

[英]Algoriithm to store dist(node, start) for all nodes in an undirected graph

The goal is to create an array called siz that stores the length of all the paths from a starting node.目标是创建一个名为 siz 的数组,用于存储从起始节点开始的所有路径的长度。 In the ideal case, I would call f(start) and expect siz[v] to get filled up for all vertices v in the graph.在理想情况下,我会调用 f(start) 并期望 siz[v] 为图中的所有顶点 v 填满。

This the algorithm that I am using.这是我正在使用的算法。

def f (node):
    vis[node] = 1
    for elem in adj[node]:
        if vis[elem]==0:
            for i in siz[node]:
                    siz[elem].append(i + w[(node,elem)])
            f(elem)

Variable descriptions:变量说明:

  1. adj[cur_nod] contains all the neighbors of the node cur_nod adj[cur_nod] 包含节点 cur_nod 的所有邻居
  2. siz[cur_nod] (which is a list not an int data type) contains all the distances from node 1 to node cur_nod siz[cur_nod] (这是一个列表而不是 int 数据类型)包含从节点 1 到节点 cur_nod 的所有距离
  3. w(x,y) denotes the weight of the edge joining the nodes x and y w(x,y) 表示连接节点 x 和 y 的边的权重
  4. vis[nod] tracks if a node is visited. vis[nod] 跟踪节点是否被访问。 0 for not, 1 for visited. 0 表示未访问,1 表示已访问。

The recursion doesn't seem correct and I don't know when to actually mark a node as visited.递归似乎不正确,我不知道何时将节点实际标记为已访问。 Also, since there are cycles, I do not want distances to include cycles.另外,由于有循环,我不希望距离包括循环。 For instance, A -> B -> C -> A -> D should not be a case at all.例如,A -> B -> C -> A -> D 根本不应该是一个案例。 It should just be A -> D or all other ways there is a path from A to D without going through a cycle.它应该只是 A -> D 或所有其他方式,从 A 到 D 的路径不经过循环。

To give an example of how this algorithm doesn't work as intended:举例说明此算法如何无法按预期工作:

If I enter the nodes and the edge weights as w(1,2)=1, w(2,3)=2, w(2,4)=7 and w(3,4)=1.如果我输入节点和边权重为 w(1,2)=1, w(2,3)=2, w(2,4)=7 和 w(3,4)=1。

Then siz = [[-1], [0], [1], [3], [4]].然后 siz = [[-1], [0], [1], [3], [4]]。 (Do note that I have set siz[1]=0 and siz[0]=-1 initially since my start node is 1 and the array is 0-indexed but I need it as 1-indexed) while the ideal siz should have been [[-1], [0], [1], [3,9], [4,8]] (请注意,我最初设置了 siz[1]=0 和 siz[0]=-1,因为我的起始节点是 1 并且数组是 0-indexed 但我需要它作为 1-indexed)而理想的尺寸应该有曾经 [[-1], [0], [1], [3,9], [4,8]]

What you may do is simply consider the current path you are traversing.您可以做的只是考虑您正在穿越的当前路径。 For the last visited node, create the corresponding new path and add it to ' siz ' which I renamed to node_paths .对于最后访问的节点,创建相应的新路径并将其添加到我重命名为node_paths的“ siz ”。 Then recurse for every neighbour.然后递归每个邻居。

Since the path given to f (see below code) is a copy you don't have to manually remove the added node (However, if eg you use path.append(node) , when you quit f , you would thus have to path.pop() )由于给f的路径(见下面的代码)是一个副本,您不必手动删除添加的节点(但是,如果您使用path.append(node) ,当您退出f时,您将因此必须path.pop() )


data = [
(1, 2, 1),
(1, 3, 2),
(2, 4, 4),
(3, 4, 8),
]
adj = {}
w = {}
node_paths = {}
for (src, dst, weight) in data:
  if src not in adj:
    adj[src] = []
  if dst not in adj:
    adj[dst] = []

  adj[src].append(dst)
  adj[dst].append(src)
  w[(src, dst)] = weight
  w[(dst, src)] = weight

def f (path, weight, node, node_paths):
  if node in path:
    return
  path_to_node = path + [node]
  weight_to_node = weight + w[(path[-1], node)]
  if node not in node_paths:
    node_paths[node] = []
  node_paths[node].append((path_to_node[1:], weight_to_node))
  for neigh in adj[node]:
    f(path_to_node, weight_to_node, neigh, node_paths)

node_paths = {}
start = 1
w[(-1, start)] = 0
f([-1], 0, start, node_paths)
print(node_paths)

#{1: [([1], 0)], 2: [([1, 2], 1), ([1, 3, 4, 2], 14)], 4: [([1, 2, 4], 5), ([1, 3, 4], 10)], 3: [([1, 2, 4, 3], 13), ([1, 3], 2)]}

In code above, I store both the path and the weighted sum to ease debug, but you may obviously discard the stored path在上面的代码中,我存储了路径和加权和以方便调试,但您显然可能会丢弃存储的路径

A few points:几点:

  • When debugging just avoid asking user input and hardcode stuff it helps reproducibility and fasten tries调试时只是避免询问用户输入和硬编码的东西,它有助于重现性并加快尝试
  • A nice property of 1,2,4,8 is that (given the binary representation) any combination (among the numbers) you take will yield a different sum which "uniquely" describes your path (even if there we just have the path at disposal anyway) 1,2,4,8 的一个很好的属性是(给定二进制表示)您采用的任何组合(在数字中)都会产生一个不同的总和,该总和“唯一”描述您的路径(即使我们只有在无论如何处置)
  • I did not follow your algorithm spirit because I think it fails for diamond graphs like the one above (even if no cycle in a directed graph) (since we would probably cumulate identical paths)(but I just guessed it, not tested the guess, and may be wrong)我没有遵循您的算法精神,因为我认为对于像上面这样的菱形图它失败了(即使有向图中没有循环)(因为我们可能会累积相同的路径)(但我只是猜到了,没有测试猜想,并且可能是错误的)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在无向图中找到节点的平均值 - Finding the mean of nodes in an undirected graph 使用networkx计算加权无向图中连接到一个节点的每个子图中的节点和边数 - Count the number of nodes and edges in each subgraph connected to one node in a weighted undirected graph with networkx 我有一个无向的NetworkX图,想找到所有的node_a邻居,它们也是node_b的邻居 - I've an undirected NetworkX graph and want to find all neighbors of node_a that are also neighbors of node_b 在十亿个节点的无向​​图中无循环地从正好k个边的源节点中找到目标节点的算法/方法 - Algorithm/Approach to find destination node from source node of exactly k edges in undirected graph of billion nodes without cycle 在有向图和无向图中查找所有循环 - Find all cycles in directed and undirected graph 根据边的权重从加权无向图提取连接节点 - extracting connected nodes from weighted undirected graph based on the weight of the edges networkx python,有向/无向图,节点和边不一致? - networkx python, directed/undirected graph, inconsistent nodes and edges? NetworkX - 创建属于4节点集团的所有节点的新图形 - NetworkX — Create new graph of all nodes that are a part of 4-node clique "如何在有向无环图中找到每个节点的所有父节点?" - How to find all the parent nodes of each node in a directed acyclic graph? 查找图中没有起点或终点的所有路径 - find all paths in graph without start or end node
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM