leetcode打卡——1584. 连接所有点的最小费用
Posted C_YCBX Py_YYDS
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode打卡——1584. 连接所有点的最小费用相关的知识,希望对你有一定的参考价值。
题目
题目解析
很明显的最小生成树问题,直接用Prim算法或者Kruskal算法即可!
解题代码
朴素Prim算法
class Solution {
public:
// 基本版本的Prim算法
vector<int>path;
vector<int>cost;
int res;
int get_cost(vector<int>&p1,vector<int>&p2){
return abs(p1[0]-p2[0])+abs(p1[1]-p2[1]);
}
int FindMin(){
int minV=INT_MAX,node=-1;
for(int i=0;i<cost.size();i++){
if(path[i]!=-1&&cost[i]<minV){
minV = cost[i];
node = i;
}
}
if(node!=-1){
path[node] = -1;//表示点和对应的边已经被选中
res += cost[node];
}
return node;
}
int minCostConnectPoints(vector<vector<int>>& points) {
res = 0;
int n = points.size();
path.resize(n),cost.resize(n);
fill(cost.begin(),cost.end(),INT_MAX);
//初始化
for(int i=1;i<n;i++){
cost[i] = get_cost(points[0],points[i]);
path[i] = 0;
}
path[0] = -1;//表示这个点已经被选
//以下开始正式选边和点,以及更新可选择的边
for(int i=0;i<n;i++){
int node = FindMin();
if(node==-1)
break;
for(int i=1;i<n;i++){
int new_cost = get_cost(points[node],points[i]);
if(path[i]!=-1&&cost[i]>new_cost){
cost[i] = new_cost;
path[i] = node;
}
}
}
return res;
}
};
优先队列Prim算法
class Solution {
public:
struct Node {
int j;
int cost;
Node(int j, int cost): j(j), cost(cost) {}
bool operator<(const Node& a)const {
return cost > a.cost;
}
};
vector<bool>visit;
priority_queue<Node>pq;
int res;
int get_cost(vector<int>&p1, vector<int>&p2) {
return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1]);
}
int minCostConnectPoints(vector<vector<int>>& points) {
res = 0;
int n = points.size();
int count = n - 1;
visit.resize(n);
//初始化
for (int i = 1; i < n; i++) {
pq.push(Node(i, get_cost(points[0], points[i])));
}
visit[0] = true;
//开始进行答案更新,利用优先队列以边扩散更新
while (!pq.empty() && count > 0) {
Node t = pq.top(); pq.pop();
int node = t.j;
if (!visit[node]) {
visit[node] = true;
res += t.cost;
count--;
for (int i = 0; i < n; i++) {
if (!visit[i]) {
pq.push(Node(i, get_cost(points[node], points[i])));
}
}
}
}
return res;
}
};
Kruskal算法
class UnionFind{
public:
int* root;
UnionFind(int n):root(new int[n]){
for(int i=0;i<n;i++){
root[i] = i;
}
}
int find(int node){
if(root[node] == node)
return node;
return root[node] = find(root[node]);
}
void connect(int a,int b){
int x = find(a);
int y = find(b);
if(x!=y){
root[x] = root[y];
}
}
bool isConnect(int a,int b){
return find(a)==find(b);
}
};
class Solution {
public:
//Kruskal算法实现
struct Node {
int i;
int j;
int cost;
Node(int i,int j, int cost):i(i), j(j), cost(cost) {}
bool operator<(const Node& a)const {
return cost > a.cost;
}
};
priority_queue<Node>pq;
int res;
int get_cost(vector<int>&p1, vector<int>&p2) {
return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1]);
}
int minCostConnectPoints(vector<vector<int>>& points) {
res = 0;
int n = points.size();
UnionFind check(n);
int count = n-1;
//把所有的边存进去,然后选择最短的边
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
pq.push(Node(i,j,get_cost(points[i],points[j])));
}
}
//一直取最小的边,然后根据并查集判断是否形成环,由于是n个点,所以就是n-1条边
while(!pq.empty()){
auto t = pq.top();pq.pop();
//如果两个点不是同一个部分,则进行合并,并且选择该边,如果形成了环则该边不选
if(!check.isConnect(t.i,t.j)){
count--;
check.connect(t.i,t.j);
res += t.cost;
}
if(count==0)
break;
}
return res;
}
};
以上是关于leetcode打卡——1584. 连接所有点的最小费用的主要内容,如果未能解决你的问题,请参考以下文章
算法千题案例每日LeetCode打卡——98.字符的最短距离