主页 > 软件开发  > 

力扣1584.连接所有点的最小费用

力扣1584.连接所有点的最小费用
力扣1584. 连接所有点的最小费用 题目

题目解析及思路

题目要求返回最小生成树

最小生成树模版题

法一:prim

主要思想是每次找离树最近的顶点,将其加入树种,并更新其他所有点到该点的距离

代码 class Solution { public: int minCostConnectPoints(vector<vector<int>>& points) { int n = points.size(); int res = 0; int st = 0; vector<vector<int>> g(n,vector<int>(n)); //建图 for(int i=0;i<n;i++){ for(int j=i+1;j<n;j++){ int dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]); g[i][j] = g[j][i] = dist; } } //存每个点到集合的最近距离 vector<int> lowcost(n,INT_MAX); //已经加入集合的点不用再看 vector<int> v(n); //从任意一个点开始即可,因为所有点最终都会进入集合,这里st = 0 v[st] = 1; //初始化lowcost,目前只有st一个点 for(int i=0;i<n;i++){ if(i == st) continue; lowcost[i] = g[i][st]; } //枚举所有店 for(int i = 1;i<n;i++){ //t为下一个放进集合的点的下标 int t = -1; //minv为下一个放进集合的点的权值 int minv = INT_MAX; //枚举所有点 for(int j=0;j<n;j++){ //找到lowcost最小的那个 if(v[j] == 0 && lowcost[j] < minv){ t = j; minv = lowcost[j]; } } //标记,并在res中加入权值 v[t] = 1; res += minv; //更新其他没进入集合的点到集合的距离 for(int j=0;j<n;j++){ if(v[j] == 0 && lowcost[j] > g[j][t]){ lowcost[j] = g[j][t]; } } } return res; } }; 法二:kruskal

与prim不同,kruskal是每次找最短的边,看该边的两端是否已经联通,如果没有就连接,要用并查集

代码 class Djset{ public: //并查集p数组 vector<int> parent; //记录树的大小 vector<int> size; //存权值之和 vector<int> len; int num; Djset(int n) : parent(n),rank(n),len(n,0),size(n,1),num(n){ for(int i=0;i<n;i++){ parent[i] = i; } } int find(int x){ if(x != parent[x]){ parent[x] = find(parent[x]); } return parent[x]; } //将x和y两点加入集合,权值为length int merge(int x,int y,int length){ //找双亲 int rootx = find(x); int rooty = find(y); //如果没连接 if(rootx != rooty){ parent[rooty] = rootx; //更新集合的大小 size[rootx] += size[rooty]; //更新总权值 len[rootx] += len[rooty] + length; //只有当全部点加入集合才返回总权值,否则都是-1 if(size[rootx] == num) return len[rootx]; } return -1; } }; struct Edge{ int start; int end; int len; }; class Solution { public: int minCostConnectPoints(vector<vector<int>>& points) { int res = 0; int n = points.size(); Djset ds(n); vector<Edge> edges; //把所有边信息加入结构体数组 for(int i=0;i<n;i++){ for(int j=i+1;j<n;j++){ Edge edge = {i, j, abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])}; edges.emplace_back(edge); } } //根据权值排序 sort(edges.begin(),edges.end(),[](const auto& a,const auto& b){ return a.len < b.len; }); //每次找一条边加入集合 for(auto& e:edges){ res = ds.merge(e.start,e.end,e.len); //只有当所有点都入图res才不是-1 //才会return if(res != -1) return res; } return 0; } };
标签:

力扣1584.连接所有点的最小费用由讯客互联软件开发栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“力扣1584.连接所有点的最小费用