力扣(leetcode)#1584 连接所有点的最小费用(#1)
题目
原题链接:力扣(LeetCode)#1584
解析
利用Kruskal 算法生成最小生成树,利用并查集,路径压缩等知识。
代码(含注释)
class Solution {
private:
int n;//点的个数
struct edge
{
int s,e;//开始和结束的点
int w;//权重
};
edge e[1000005];//数组要开大些,不然会爆
int fa[1000005];//父节点
int cnt=0;
public:
//首先是初始化,需要设置每一个点的父节点是自己
void init()
{
for(int i=0;i<n;i++)
{
fa[i]=i;
}
}
//寻找父节点
int find(int val)
{
if(val==fa[val])//当两者相等的时候说明是父节点
return val;
else
return fa[val]=find(fa[val]);//路径压缩,设置父节点是根节点
}
//父节点合并
bool merge(int x, int y)
{
int fa1=find(x);
int fa2=find(y);
if(fa1!=fa2)
{
fa[fa1]=fa2;
return true;
}
else
return false;
}
static int cmp(edge a, edge b)
{
return a.w<b.w;
}
int minCostConnectPoints(vector<vector<int>>& points) {
n=points.size();
init();
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
e[cnt++]={i,j,abs(points[i][0]-points[j][0])+abs(points[i][1]-points[j][1])};
}
}
sort(e,e+cnt,cmp);//对路径长度进行排序
int sum=0;//权值和
for(int i=0;i<cnt;i++)
{
if(merge(e[i].s,e[i].e))//如果不在同一个集合里就要加上权值
{
sum+=e[i].w;
}
}
return sum;
}
};
本质上Kruskal算法是贪心的思想,并查集是为了维护连通性。
代码总结
总共分为三个函数,init(初始化),find(寻找父节点),merge(合并),其次修改数据的存储即可,本方法不是最优解,时间复杂度有点高。
备注
第一次开始博客的制作,算法新人,代码多少会有错误,还望海涵。
并查集部分参考的是算法学习笔记(1) : 并查集,写得极好,一看就明白了。