简体   繁体   English

如何从给定的节点集中等距离地查找图中的所有节点?

[英]How to find all nodes in a graph equidistant from a given set of nodes?

If you have a simple undirected graph G(V,E) and F which is a subset of V . 如果你有一个简单的无向图G(V,E)F ,它是V的子集。 How can you find some node v such that the distance from every node in F to v is the same and the distances are minimized? 如何找到某个节点v ,使得从Fv每个节点的距离相同,距离最小化? And just return None if there is no v . 如果没有v ,则返回None I was told this can be done in O(|V|+|E|) complexity. 我被告知这可以在O(|V|+|E|)复杂度中完成。

Assume all edges are of distance 1. 假设所有边都距离为1。

Can anyone explain how this can be done? 任何人都可以解释如何做到这一点? A pseudo-code would also help. 伪代码也会有所帮助。

The solution is similar to BFS, but with a little change: 该解决方案类似于BFS,但稍有改动:

  1. Start with S = F with F nodes marked. 从S = F开始,标记F节点。

  2. Find |S| 查找| S | sets with distance 1 from each element in S (all these sets should contain unmarked nodes). 从S中的每个元素设置距离1(所有这些集合应包含未标记的节点)。 If the intersection of these sets is non-empty, the candidate is found. 如果这些集合的交集非空,则找到候选者。

  3. Take the union of the |S| 取| S |的并集 sets above in S' and mark these nodes. 在S'中设置上面并标记这些节点。 If S' is empty, return 'None'. 如果S'为空,则返回“无”。

  4. Return to step 2. 返回第2步。

Suppose all the set operations take constant time, then the complexity of the algorithm is same as BFS which is O(|V| + |E|). 假设所有设置操作都需要恒定时间,那么算法的复杂度与BFS相同,即O(| V | + | E |)。

Now to reason about the complexity of set operations. 现在来推断集合操作的复杂性。 My reasoning is that the set operations don't increase the complexity as the union and intersection operations in steps 2 and 3 can be combined to take time O(|S|), and since at every step S is different from S in previous iterations, the overall complexity of set operations would be O(|V|). 我的理由是,设置操作不会增加复杂性,因为步骤2和3中的并集和交叉操作可以组合起来花费时间O(| S |),并且因为在每个步骤S与之前迭代中的S不同,集合操作的总体复杂度为O(| V |)。

Here is one algorithm, in pseudo-code, trying to add comments to explain how it works. 这是一种算法,在伪代码中,试图添加注释来解释它是如何工作的。

declare explored // a table of all the vertices that can keep track of one number (distance, initialized to -1) and a list of vertex references (origins, initialized to null)
to_explore = S  // fifo queue of vertices to explore

while (to_explore not empty) {
    pop vertex v from to_explore
    current_distance = explored[v].distance
    current_origins = explored[v].origins
    for (vertex n, neighbor of v) {
        if (explored[n].origins contains v)
            continue // we just hit a loop and we're only interested in shortest distances
        if (explored[n].distance == -1) { // first time we come here
            explored[n].distance = current_distance+1
            explored[n].origins = current_origins
            push n to to_explore
            continue
        }
        if (explored[n].distance != current_distance+1) {
            continue // we are merging path from another node of S but different distance, cannot lead to any solution
        }
        // only case left is explored[n].distance == current_distance+1
        // so we've already come here from other place(s) in S with the same distance
        add / merge (without duplicates) origins to explored[n].origins
        if (explored[n].origins = S) // maybe compare the size is enough?
            return n // we found a solution
        // if not , we just continue our exploration, no need to add to the queue since we've already been through here before
    }
}

The idea is that with the FIFO queue, we will explore everything that's at distance 1 from the set S, if we cannot find any solution there, everything at distance 2...etc.. so we'll find the shortest distance first. 我们的想法是,通过FIFO队列,我们​​将探索距离集合S 1的距离,如果我们在那里找不到任何解决方案,距离2处的所有内容......等等,我们将首先找到最短距离。

I am not completely sure about the complexity, but I believe that in the worst case, we only explore every vertex and every edge only once so that would give O(|E| + |V|) . 我不完全确定复杂性,但我相信在最坏的情况下,我们只探索每个顶点和每个边缘一次,这样就会得到O(|E| + |V|) But in some case we visit the same vertex multiple times. 但在某些情况下,我们多次访问相同的顶点。 Although that does not increase the paths to explore much, I am not sure if there should be a factor |S| 虽然这不会增加探索的路径,但我不确定是否应该有一个因素| S | somewhere (but if that is just considered like a constant, then it's ok...) 在某个地方(但如果这只是一个常数,那就没关系......)

Hope I did not miss anything. 希望我没有错过任何东西。 Obviously I did not test any of this.... :) 显然我没有测试任何这个...... :)

EDIT (reply to comment) 编辑 (回复评论)

Will your code work for a graph like this? 你的代码是否适用于这样的图形? E = ( a, b), (a, c), (a,d) , (b,e), (c,e), (d, e), and my F = { b, c , d}. E =(a,b),(a,c),(a,d),(b,e),(c,e),(d,e),并且我的F = {b,c,d}。 Say, you start your bfs with a. 说,你用一个开始你的bfs。 I suspect, in the end the origins array will only have {a} and therefore the code will return None. 我怀疑,最终genins数组只有{a},因此代码将返回None。 – Guru Devanla - Guru Devanla

In this case, here is what happens: 在这种情况下,会发生以下情况:

to_explore is initialized to {b,c,d}
//while (to_explore not empty)
pop one from to_explore (b). to_explore becomes {c,d}
current_distance=0
current_origins={b}
//for (neighbors of b) {
handling 'a' as neighbor of b first
explored[a].distance=1
explored[a].origins={b}
to_explore becomes {c,d,a}
//for (neighbors of b)
handling 'e' as next neighbor of b
explored[e].distance=1
explored[e].origins={b}
to_explore becomes {c,d,a,e}
//while (to_explore not empty)
pop one from to_explore (c). to_explore becomes {d,a,e}
current_distance=0
current_origins={c}
//for (neighbors of c)
handling 'a' as neighbor of c first
explored[a].distance is already 1
explored[a].origins={b,c}
to_explore already contains a
//for (neighbors of c) {
handling 'e' as next neighbor of b
explored[e].distance is already 1
explored[e].origins={b,}
to_explore already contains e
//while (to_explore not empty)
pop one from to_explore (d)
current_distance=0
current_origins={d}
//for (neighbors of d)
handling 'a' as neighbor of d first
explored[a].distance is already 1
explored[a].origins={b,c,d}
that matches F, found a as a solution.

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

相关问题 如何从给定的路由中找到最小的一组路由来访问图中的所有节点? - How to find a minimal set of routes to visit all nodes in a graph from a given set of routes? 在有向图中查找所有其他节点均可访问的节点 - Find nodes in directed graph that is reachable from all other nodes 如何找到一个在图中包含一组节点的循环? - How to find a cycle containing a set of nodes in a graph? 如何检查图中的所有节点是否可以从所有其他节点访问? - How to check if all nodes in a graph are reachable from all other nodes? 在图中查找不在循环中的所有节点 - Find all nodes that are not in cycle in a graph 如何检查给定的节点集是否是图的顶点割集? - How to check if given set of nodes is the vertex cut set of the graph? 将具有给定集合的最大可能边添加到具有节点容量的图形中 - Add maximum possible edges from given set to the graph with nodes capacity 如何在有向图中找到彼此距离 k 的所有节点(探索图中的每条边)? - How to find all nodes distance k away from each other in directed graph (exploring every edge in a graph)? 查找具有给定节点数和边数的图的算法 - Algorithm to find a graph with given number of nodes and edges 如何在DAG中找到通过一组给定节点的所有路径? - How do I find all paths through a set of given nodes in a DAG?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM