如果您有一个简单的无向图G(V,E)
和F
,它是V
的子集。如何找到某个节点v
,使F
到v
中每个节点的距离相同,距离最小化?如果没有None
,请返回v
。我被告知这可以在O(|V|+|E|)
复杂性中完成。
假设所有边都距离为1。
任何人都可以解释如何做到这一点?伪代码也会有所帮助。
答案 0 :(得分:3)
解决方案类似于BFS,但稍作修改:
从S = F开始,标记F节点。
查找| S |从S中的每个元素设置距离1(所有这些集合应包含未标记的节点)。如果这些集合的交集非空,则找到候选者。
取| S |的并集在S'中设置上面并标记这些节点。如果S'为空,则返回“无”。
返回第2步。
假设所有设置操作都需要恒定时间,那么算法的复杂度与BFS相同,即O(| V | + | E |)。
现在推断集合操作的复杂性。我的理由是,设置操作不会增加复杂性,因为步骤2和3中的并集和交叉操作可以组合起来花费时间O(| S |),并且因为在每个步骤S与之前迭代中的S不同,集合操作的总体复杂度为O(| V |)。
答案 1 :(得分:2)
这是一种伪代码算法,试图添加注释来解释它是如何工作的。
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
}
}
我们的想法是,通过FIFO队列,我们将探索距离集合S的距离为1的所有内容,如果我们在那里找不到任何解决方案,距离2处的所有内容......等等。所以我们会找到最短的距离第一。
我并不完全确定复杂性,但我相信在最坏的情况下,我们只会探索每个顶点和每个边缘一次,这样才能得到O(|E| + |V|)
。但在某些情况下,我们多次访问相同的顶点。虽然这不会增加探索的路径,但我不确定是否应该有一个因素| S |在某个地方(但如果这只是一个常数,那就没问题了......)
希望我没有错过任何东西。显然我没有测试任何这个.... :)
编辑(回复评论)
您的代码是否适合这样的图表? E =(a,b),(a,c),(a,d) ,(b,e),(c,e),(d,e),我的F = {b,c,d}。说,你开始吧 bfs用。我怀疑,最终genins数组只有{a} 因此代码将返回None。 - Guru Devanla
在这种情况下,会发生以下情况:
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.