Kruskal算法
相比于Prim算法,Kruskal算法实现原理更简单,但是前置工作比较复杂(建立并查集和最小堆)
如不使用堆,可以将所有边进行排序,从小到大,再寻求并查集,查找并入最小生成树
#include<iostream>
#include<string>
#include<vector>
#include<queue>
#define INF 100000
#define MaxVertex 105
typedef int Vertex;
int G[MaxVertex][MaxVertex];
int parent[MaxVertex]; // 并查集最小生成树
int Nv; // 结点
int Ne; // 边
int sum; // 权重和
using namespace std;
struct Node{
Vertex v1;
Vertex v2;
int weight;
//重载运算符最大堆
bool operator < (const Node &a) const{
return weight > a.weight;
}
};
vector<Node> MST; //最小生成树
priority_queue<Node> q; //最小堆
void build(){
Vertex v1,v2;
int w;
cin>>Nv>>Ne;
for(int i=1;i<=Nv;i++){
for(int j=1;j<=Nv;j++)
G[i][j] = 0; // 初始化图
parent[i] = -1;
}
// 初始化点
for(int i=0;i<Ne;i++){
cin>>v1>>v2>>w;
struct Node tmpE;
tmpE.v1 = v1;
tmpE.v2 = v2;
tmpE.weight = w;
q.push(tmpE);
}
}
int Find(int x)
{
if(parent[x] < 0)
return x;
else
return parent[x] = Find(parent[x]);
//并查集——查
}
//按秩归并
void Union(int x1,int x2)
{
x1 = Find(x1);
x2 = Find(x2);
if(parent[x1] < parent[x2]){
parent[x1] += parent[x2];
parent[x2] = x1;
}else{
parent[x2] += parent[x1];
parent[x1] = x2;
}
}
void Kruskal()
{
//当最小生成树的边少于Nv-1的边时还有边
while(MST.size() != Nv-1 && !q.empty()){
Node E = q.top(); //最小堆中选出最小边
q.pop();
if(Find(E.v1) != Find(E.v2)){
//两边不在一个集合时,可以并
sum += E.weight;
Union(E.v1 , E.v2);
MST.push_back(E);
}
}
}
void output()
{
cout<<"Enter num : "<<endl;
for(Vertex i=1;i<=Nv;i++){
cout<<MST[i].weight<<" ";
}
cout<<endl;
cout<<"Total Weight :"<<sum<<endl;
for(Vertex i=1;i<=Nv;i++){
cout<<parent[i]<<" ";
}
cout<<endl;
}
int main()
{
build();
Kruskal();
output();
return 0;
}