最小生成树的运行时间? (普里姆法)
我编写了一个使用 Prim 方法求解 MST 的代码。我读到这种实现(使用优先级队列)应该有 O(E + VlogV) = O(VlogV),其中 E 是边数,V 是边数,但是当我查看我的代码时,它根本不看起来如果有人能为我解决这个问题,我将不胜感激。
对我来说,运行时间似乎是这样的:
while 循环需要 O(E) 次(直到我们遍历所有边缘) 在该循环中,我们从 Q 中提取一个元素,这需要 O(logE) 时间。 第二个内部循环需要 O(V) 时间(尽管我们不会每次都运行这个循环 很明显,它将运行 V 次,因为我们必须添加所有顶点)
我的结论是运行时间为:O( E(logE+V) ) = O( E*V )。
这是我的代码:
#define p_int pair < int, int >
int N, M; //N - nmb of vertices, M - nmb of edges
int graph[100][100] = { 0 }; //adj. matrix
bool in_tree[100] = { false }; //if a node if in the mst
priority_queue< p_int, vector < p_int >, greater < p_int > > Q;
/*
keeps track of what is the smallest edge connecting a node in the mst tree and
a node outside the tree. First part of pair is the weight of the edge and the
second is the node. We dont remember the parent node beaceuse we dont need it :-)
*/
int mst_prim()
{
Q.push( make_pair( 0, 0 ) );
int nconnected = 0;
int mst_cost = 0;
while( nconnected < N )
{
p_int node = Q.top(); Q.pop();
if( in_tree[ node.second ] == false )
{
mst_cost += node.first;
in_tree[ node.second ] = true;
for( int i = 0; i < N; ++i )
if( graph[ node.second ][i] > 0 && in_tree[i]== false )
Q.push( make_pair( graph[ node.second ][i], i ) );
nconnected++;
}
}
return mst_cost;
}
I have written a code that solves MST using Prim method. I read that this kind of implementation(using priority queue) should have O(E + VlogV) = O(VlogV) where E is the number of edges and V number of Edges but when I look at my code it simply doesn't look that way.I would appreciate it if someone could clear this up for me.
To me it seems the running time is this:
The while loop takes O(E) times(until we go through all the edges)
Inside that loop we extract an element from the Q which takes O(logE) time.
And the second inner loop takes O(V) time(although we dont run this loop everytime
it is clear that it will be ran V times since we have to add all the vertices )
My conclusion would be that the running time is: O( E(logE+V) ) = O( E*V ).
This is my code:
#define p_int pair < int, int >
int N, M; //N - nmb of vertices, M - nmb of edges
int graph[100][100] = { 0 }; //adj. matrix
bool in_tree[100] = { false }; //if a node if in the mst
priority_queue< p_int, vector < p_int >, greater < p_int > > Q;
/*
keeps track of what is the smallest edge connecting a node in the mst tree and
a node outside the tree. First part of pair is the weight of the edge and the
second is the node. We dont remember the parent node beaceuse we dont need it :-)
*/
int mst_prim()
{
Q.push( make_pair( 0, 0 ) );
int nconnected = 0;
int mst_cost = 0;
while( nconnected < N )
{
p_int node = Q.top(); Q.pop();
if( in_tree[ node.second ] == false )
{
mst_cost += node.first;
in_tree[ node.second ] = true;
for( int i = 0; i < N; ++i )
if( graph[ node.second ][i] > 0 && in_tree[i]== false )
Q.push( make_pair( graph[ node.second ][i], i ) );
nconnected++;
}
}
return mst_cost;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以使用邻接表来加速您的解决方案(但不适用于密集图),但即便如此,如果没有斐波那契堆,您也不会得到 O(V log V) 。
也许 Kruskal 算法 会让您更容易理解。它没有优先级队列,您只需对边数组进行一次排序。基本上是这样的:
唯一的问题是能够快速判断两个节点是否已连接。为此,您使用并查数据结构,如下所示:
一开始,只需将 T 初始化为全 -1,然后每次您想查明节点 A 和 B 是否连接时,只需比较它们的父节点 -如果它们相同,则它们是连接的(就像这样
getParent(A)==getParent(B)
)。将边插入 MST 时,请确保使用Unite(getParent(A),getParent(B))
更新并查。分析很简单,您对边进行排序并使用需要 O(1) 的 UF 进行迭代。所以它是 O(E logE + E ) 等于 O(E log E)。
就是这样;-)
You can use adjacency lists to speed your solution up (but not for dense graphs), but even then, you are not going to get O(V log V) without a Fibonacci heap..
Maybe the Kruskal algorithm would be simpler for you to understand. It features no priority queue, you only have to sort an array of edges once. It goes like this basically:
The only catch is to be quickly able to say if two nodes are connected. For this you use the Union-Find data structure, which goes like this:
In the beginning, just initialize T to all -1, and then every time you want to find out if nodes A and B are connected, just compare their parents - if they are the same, they are connected (like this
getParent(A)==getParent(B)
). When you are inserting the edge to MST, make sure to update the Union-Find withUnite(getParent(A),getParent(B))
.The analysis is simple, you sort the edges and iterate over using the UF that takes O(1). So it is O(E logE + E ) which equals O(E log E).
That is it ;-)
我之前不需要处理该算法,但是您所实现的与
这
正是人们所期望的。
I did not have to deal with the algorithm before, but what you have implemented does not match the algorithm as explained on Wikipedia. The algorithm there works as follows.
This gives
exactly what one expects.