您的位置:首页 > 其它

hiho 29 最小生成树三·堆优化的Prim算法

2016-01-23 16:54 330 查看

问题描述

最小生成树算法,在稀疏图时,Kruscal复杂度更低,我们可以使用堆优化的prim算法达到与Kruscal一样的复杂度。

Prim算法本身的时间复杂度是O(N^2)的,而在这个算法中,使用了堆来维护所有的边,操作数一共是O(M)级别的,所以复杂度是O(MlogM)的!而Kruscal算法的时间复杂度是O(MlogM + M * Ackermann’(M)),总的说来,是优化到了和Kruscal算法同样级别了呢。”

prim 算法对应于dijstra算法。dijistra算法也可以用堆进行优化。

STL中heap函数

参考这个例子中,注意push_heap 和 pop_heap只是改变vector中元素位置,并不会插入或删除元素,所以要配合vector.push_back() 和 vector.pop_back()使用!

// range heap example
#include <iostream>     // std::cout
#include <algorithm>    // std::make_heap, std::pop_heap, std::push_heap, std::sort_heap
#include <vector>       // std::vector

int main () {
int myints[] = {10,20,30,5,15};
std::vector<int> v(myints,myints+5);

std::make_heap (v.begin(),v.end());
std::cout << "initial max heap   : " << v.front() << '\n';

std::pop_heap (v.begin(),v.end()); v.pop_back();
std::cout << "max heap after pop : " << v.front() << '\n';

v.push_back(99); std::push_heap (v.begin(),v.end());
std::cout << "max heap after push: " << v.front() << '\n';

std::sort_heap (v.begin(),v.end());

std::cout << "final sorted range :";
for (unsigned i=0; i<v.size(); i++)
std::cout << ' ' << v[i];

std::cout << '\n';

return 0;
}


#include <vector>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
enum {maxn = 100000+5};
struct Node{
int a, b;
int w;
// 构建小顶堆
bool operator <(const struct Node &n)const{
return w> n.w;
}
};
vector<Node> edge;
vector<Node> G[maxn];
bool visted[maxn];
void inline m_pop() {pop_heap(edge.begin(), edge.end()); edge.pop_back();}
void inline m_push(struct Node &n)
{
edge.push_back(n);
push_heap(edge.begin(), edge.end());
}
int main()
{
//freopen("in.txt", "r", stdin);
int N, M;
scanf("%d %d", &N, &M);
memset(visted, 0, sizeof(visted));
for (int i=0; i< M; i++)
{
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
G[a].push_back(Node{a, b, c});
G[b].push_back(Node{b, a, c});
}
visted[1] = true;
for(int i=0; i< G[1].size(); i++)
{
m_push(G[1][i]);
}

int all =0;
int cnt = 0;
while(cnt < N-1){
int w = edge[0].w;
int n = edge[0].b;
m_pop();

if (visted
){
continue;
}

visted
= true;
all += w;
cnt ++;
for (int i=0; i< G
.size(); i++)
{
if (!visted[G
[i].b])
m_push(G
[i]);
}
}
printf("%d\n", all);
return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  prim