最小生成树
算法简介
一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。 最小生成树可以用kruskal(克鲁斯卡尔)算法或prim(普里姆)算法求出。简言之就是在一个连通图中找出一些边使得所有节点联通。
算法描述
虽然有很多可以实现最小生成树的算法,我们只讨论Kruskal算法。
Kruskal(克鲁斯科尔算法)
该算法算是贪心算法的引用
步骤:
- 新建图G,G中拥有原图中相同的节点,但没有边
- 将原图中所有的边按权值从小到大排序
- 从权值最小的边开始,如果这条边连接的两个节点于图G中不在同一个连通分量中,则添加这条边到图G中
- 重复3,直至图G中所有的节点都在同一个连通分量中
代码描述
我们间接通过并查集来实现判断是否两个节点存在于同一个连通分量
int f[maxn];
int find(int u){
if(u==f[u])return u;
f[u]=find(f[u]);
return f[u];
}
void join(int u,int v){
int fu=find(u);
int fv=find(v);
if(fu!=fv){
f[fu]=fv;
}
}
struct edge{
int from,to,cost;
friend bool operator <(edge a,edge b){
return a.cost<b.cost;
}
}Ed[maxn];
int V,E;
int kruskal(){
sort(Ed,Ed+E);
iniuni(V);
int res=0;
for(int i=0;i<E;i++){
edge e=Ed[i];
int fu=find(Ed[i].from);
int fv=find(Ed[i].to);
if(fu!=fv){
join(e.from,e.to);
res+=e.cost;
}
}
return res;
}