我正在阅读Cormen书中的图算法。下面是该书的伪代码
MST的Prim算法
MST-PRIM (G, w, r)
for each u in G.V
u.key = infinity
u.p = NIL
r.key = 0
Q = G.V
while Q neq null
u = EXTRACT-MIN(Q)
for each v in G.Adj[u]
if (v in Q) and (w(u,v) < v.key)
v.p = u
v.key = w(u,v)
Dijkstra算法找到单源最短路径。
INITIALIZE-SINGLE-SOURCE (G,s)
for each vertex v in G.V
v.d = infinity
v.par = NIL
s.d = 0
DIJKSTRA (G, w, s)
INITIALIZE-SINGLE-SOURCE(G,s)
S = NULL
Q = G.V
while Q neq null
u = EXTRACT-MIN(Q)
S = S U {u}
for each vertex v in G.Adj[u]
RELAX(u,v,w)
我的问题是,为什么我们要检查顶点是否属于Q(v in Q
),即顶点不属于树,而在Dijkstra算法中我们不检查它。
任何原因,为什么?
答案 0 :(得分:2)
答案 1 :(得分:2)
在两种算法中,队列Q
包含所有尚未“完成”的顶点,即根据常用术语的白色和灰色(参见here)。
在Dijkstra的算法中,黑色顶点不能放松,因为如果可能的话,这意味着它的距离预先不正确(与黑色节点的属性相矛盾)。因此,无论您是否检查v in Q
都没有区别。
在Prim的算法中,可以找到一个小重量的边缘,这导致已经是黑色的顶点。这就是为什么如果我们不检查v in Q
,那么顶点v
中的值确实会发生变化。通常情况下,没关系,因为我们从未读过黑色顶点的最小权重值。但是,您的伪代码使用MinHeap数据结构。在这种情况下,顶点值的每个修改必须伴随 DecreaseKey 。显然,为黑色顶点调用 DecreaseKey 是无效的,因为它们不在堆中。这就是为什么我认为作者决定明确检查v in Q
。
一般来说,Dijkstra和Prim算法的代码通常是完全相同的,除了一个小的区别:
w(u, v)
在RELAX中是否小于D(v)
。D(u) + w(u, v)
在RELAX中减少D(v)
。答案 2 :(得分:0)
看看我个人用C ++编写的Dijkstra和Prim的实现。
它们非常相似,我将Dijkstra修改为Prim。
Dijkstra:
const int INF = INT_MAX / 4;
struct node { int v, w; };
bool operator<(node l, node r){if(l.w==r.w)return l.v>r.v; return l.w> r.w;}
vector<int> Dijkstra(int max_v, int start_v, vector<vector<node>>& adj_list) {
vector<int> min_dist(max_v + 1, INF);
priority_queue<node> q;
q.push({ start_v, 0 });
min_dist[start_v] = 0;
while (q.size()) {
node n = q.top(); q.pop();
for (auto adj : adj_list[n.v]) {
if (min_dist[adj.v] > n.w + adj.w) {
min_dist[adj.v] = n.w + adj.w;
q.push({ adj.v, adj.w + n.w });
}
}
}
return min_dist;
}
原始:
struct node { int v, w; };
bool operator<(node l, node r) { return l.w > r.w; }
int MST_Prim(int max_v, int start_v, vector<vector<node>>& adj_list) {
vector<int> visit(max_v + 1, 0);
priority_queue<node> q; q.push({ start_v, 0 });
int sum = 0;
while (q.size()) {
node n = q.top(); q.pop();
if (visit[n.v]) continue;
visit[n.v] = 1;
sum += n.w;
for (auto adj : adj_list[n.v]) {
q.push({ adj.v, adj.w });
}
}
return sum;
}