Kruskal算法
Kruskal 算法把图的边由小到大排序,在避免形成环的前提下,构造出一棵最小生成树。
首先是边结点的定义:
//边结点定义
struct edge{ //两个顶点,和边上的权值
int u , v , cost;
};
专门为它定义一种用于 sort() 的比较函数。
//比较函数
bool comp(edge& e1 , edge& e2){
return e1.cost < e2.cost;
}
把边不停加入已经遍历的集合的操作是通过并查集来优化实现的。
并查集的声明:
//并查集
vector<int> parent(N,-1);
//查询操作
int getFather(int x){
return parent[x] == -1 ? x : getFather(parent[x]);
}
//查询时候属于一个阵营
bool query(int a,int b){
return getFather(a) == getFather(b);
}
//合并操作
int merge(int a,int b){ //b来领导a和b
parent[getFather(a)] = getFather(b);
}
如果两个点在没有连接之前就已经在集合里,那连接之后就会形成环。
Kruskal 函数:
//点集合
#define N 8
edge es[N];
int Kruskal(){
sort(es,es + N,comp); //按照edge.cost从小到大排序
int res = 0;
for(int i = 0;i < N;i ++){
if(!query(es[i].u , es[i].v)){ //如果不属于同一集合就合并
merge(es[i].u , es[i].v);
res += es[i].cost;
cout<<"v"<<es[i].u+1<<"-"<<"v"<<es[i].v+1<<"加入边集合"<<endl;
}
}
return res;
}
完整代码如下:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
#define N 8
//并查集
vector<int> parent(N,-1);
//查询操作
int getFather(int x){
return parent[x] == -1 ? x : getFather(parent[x]);
}
//查询时候属于一个阵营
bool query(int a,int b){
return getFather(a) == getFather(b);
}
//合并操作
int merge(int a,int b){ //b来领导a和b
parent[getFather(a)] = getFather(b);
}
//边结点定义
struct edge{ //两个顶点,和边上的权值
int u , v , cost;
};
//比较函数
bool comp(edge& e1 , edge& e2){
return e1.cost < e2.cost;
}
//点集合
edge es[N];
int Kruskal(){
sort(es,es + N,comp); //按照edge.cost从小到大排序
int res = 0;
for(int i = 0;i < N;i ++){
if(!query(es[i].u , es[i].v)){ //如果不属于同一集合就合并
merge(es[i].u , es[i].v);
res += es[i].cost;
cout<<"v"<<es[i].u+1<<"-"<<"v"<<es[i].v+1<<"加入边集合"<<endl;
}
}
return res;
}
int main(){
es[0].u = 0;
es[0].v = 2;
es[0].cost = 10;
es[1].u = 0;
es[1].v = 4;
es[1].cost = 30;
es[2].u = 0;
es[2].v = 5;
es[2].cost = 100;
es[3].u = 1;
es[3].v = 2;
es[3].cost = 5;
es[4].u = 2;
es[4].v = 3;
es[4].cost = 50;
es[5].u = 3;
es[5].v = 5;
es[5].cost = 10;
es[6].u = 3;
es[6].v = 4;
es[6].cost = 20;
es[7].u = 4;
es[7].v = 5;
es[7].cost = 60;
cout<<Kruskal();
}
运行结果:
Kruskal 算法的时间复杂度是O(NlogN),与优化过的 Prim 算法复杂度相同。适合边稀疏的图求最小生成树。