最小生成树两种算法Kruskal、Prime。前者针对的是边,对边权升序排序然后从小到大遍历,结合并查集,直至所有点都连在一起。后者针对的是点,背模板。
leetcode-1584 连接所有点的最小费用
最小生成树模板题。
// Kruskal
class Solution {
public:
int fa[1000];
void init(int n){
for(int i = 0; i < n; ++i){
fa[i] = i;
}
}
int find(int x){
return fa[x] == x ? x : (fa[x] = find(fa[x]));
}
void merge(int x, int y){
fa[find(x)] = find(y);
}
int getDistance(const vector<int>& a, const vector<int>& b){
return abs(a[0] - b[0]) + abs(a[1] - b[1]);
}
int minCostConnectPoints(vector<vector<int>>& points) {
int n = points.size();
if(n == 1) return 0;
init(n);
vector<vector<int>> edges(n * (n - 1) / 2, vector<int>(3));
int idx = 0;
for(int i = 0; i < n; ++i){
for(int j = i + 1; j < n; ++j){
edges[idx][0] = i, edges[idx][1] = j, edges[idx][2] = getDistance(points[i], points[j]);
++idx;
}
}
auto cmp = [](const vector<int>& a, const vector<int>& b){
return a[2] < b[2];
};
sort(edges.begin(), edges.end(), cmp);
int ans = 0, cnt = 0;
for(int i = 0; i < n * (n - 1) / 2; ++i){
int p1 = edges[i][0], p2 = edges[i][1];
if(find(p1) != find(p2)){
merge(p1, p2);
ans += edges[i][2];
++cnt;
if(cnt == n - 1) break;
}
}
return ans;
}
};
// Prime
class Solution {
public:
int getDistance(const vector<int>& a, const vector<int>& b){
return abs(a[0] - b[0]) + abs(a[1] - b[1]);
}
int minCostConnectPoints(vector<vector<int>>& points) {
int n = points.size();
if(n == 1) return 0;
vector<vector<int>> graph(n, vector<int>(n));
for(int i = 0; i < n; ++i){
for(int j = 0; j < n; ++j){
graph[i][j] = getDistance(points[i], points[j]);
graph[j][i] = getDistance(points[i], points[j]);
}
}
vector<int> dis(n, INT_MAX);
vector<int> vst(n);
int ans = 0;
for(int i = 0; i < n; ++i){
int t = -1;
for(int j = 0; j < n; ++j){
if(vst[j] == 0 && (t == -1 || dis[t] > dis[j])) t = j;
}
if(i != 0) ans += dis[t];
vst[t] = 1;
for(int j = 0; j < n; ++j) dis[j] = min(dis[j], graph[t][j]);
}
return ans;
}
};