问题描述
我想知道,解决以下问题的最有效方法是什么(w.r.t.,空间和时间):
给定一个无向图 G = (V,E)、一个正数 N 和 V 中的一个顶点 S。假设 V 中的每个顶点都有一个成本值。找到连接到 S 的 N 个最高成本顶点。
例如:
G = (V,E)
V = {v1,v2,v3,v4},E = {(v1,v2),(v1,v3),(v2,v4),(v3,v4)}
v1 cost = 1
v2 cost = 2
v3 cost = 3
v4 cost = 4
N = 2,S = v1
result: {v3,v4}
解决方法
这个问题可以通过图遍历算法(例如,BFS 或 DFS)轻松解决。要找到连接到 S
的顶点,我们可以从 S
开始运行 BFS 或 DFS。由于BFS和DFS的空间和时间复杂度相同(即时间复杂度:O(V+E)
,空间复杂度:O(E)
),这里我我将使用 DFS 显示伪代码:
Parameter Definition:
* G -> Graph
* S -> Starting node
* N -> Number of connected (highest cost) vertices to find
* Cost -> Array of size V,contains the vertex cost value
procedure DFS-traversal(G,S,N,Cost):
let St be a stack
let Q be a min-priority-queue contains <cost,vertex-id>
let discovered is an array (of size V) to mark already visited vertices
St.push(S)
// Comment: if you do not want to consider the case "S is connected to S"
// then,you can consider commenting the following line
Q.push(make-pair(S,Cost[S]))
label S as discovered
while St is not empty
v = St.pop()
for all edges from v to w in G.adjacentEdges(v) do
if w is not labeled as discovered:
label w as discovered
St.push(w)
Q.push(make-pair(w,Cost[w]))
if Q.size() == N + 1:
Q.pop()
let ret is a N sized array
while Q is not empty:
ret.append(Q.top().second)
Q.pop()
让我们先描述一下过程。在这里,我运行 DFS 的迭代版本来遍历从 S
开始的图。在遍历过程中,我使用 priority-queue
来保留可从 N
到达的 S
最高成本顶点。我们可以使用一个简单的数组(甚至我们可以重用 priority-queue
数组)来代替 discovered
来记录可到达顶点的成本。
空间复杂度分析:
- 存储图形:
O(E)
- 优先队列:
O(N)
- 堆栈:
O(V)
- 对于发现的标签:
O(V)
因此,由于 O(E)
是此处的主要术语,我们可以将 O(E)
视为整体空间复杂度。
时间复杂度分析:
- DFS 遍历:
O(V+E)
- 要跟踪
N
个成本最高的顶点:- 通过维护优先队列:
O(V*logN)
- 或者使用数组:
O(V*logV)
- 通过维护优先队列:
总体时间复杂度为:O(V*logN + E)
或 O(V*logV + E)