问题描述
Kruscal算法同单源最短路径中的SPFA算法,都是只与边有关的,因此适合求解稀疏图。
算法描述
prime算法中有一个结论:对于城市i(i≠1),如果i与城市1的距离不超过其他任何城市j(j≠1)与城市1的距离,那么(1, i)这一条边一定存在于某一棵最小生成树中么?”
可以证明图中最短的边是属于最小生成树的,然后将最短边相连的两个顶点看做一个顶点,再找图中最短的边,依次类推进行N-1次就可以找到整棵树。
我们可以在开始时就讲图中的边排序,从小到大依次将边加入,只需要判断新加入的边链接的两个节点之前没有联通。可以使用并查集实现。这样算法复杂度为排序复杂度O(vlogv + v);
#include <algorithm>
#include <vector>
#include <cstdio>
using namespace std;
enum {maxn = 1000000+4};
int f[maxn];
int findF(int i){return i==f[i]? i: f[i] = findF(f[i]);}
struct Edge{
int a, b;
int w;
bool operator<(const struct Edge& e)const{
return this->w < e.w;
}
};
Edge G[maxn];
int N, M;
int main()
{
freopen("in.txt", "r", stdin);
scanf("%d %d", &N, &M);
for (int i=0; i<=N; i++)
f[i] = i;
for (int i=0; i< M; i++)
{
scanf("%d %d %d", &G[i].a, &G[i].b, &G[i].w);
}
sort(G, G+M);
int cnt =0;
int all = 0;
for (int i=0; cnt < N-1 && i< M; i++)
{
if(findF(G[i].a) != findF(G[i].b))
{
all+= G[i].w;
cnt++;
f[f[G[i].a]] = f[G[i].b];
}
}
printf("%d\n", all);
return 0;
}