
链接:1584. 连接所有点的最小费用 - 力扣(LeetCode)
题解:
1.求得所有边的距离
2.贪心:按照边距离最小的排序
3.遍历所有边,
如果边的两个点没有联通,则增加边。
如果连通过则不放入
记录连接边数量,如果边数量为节点数量-1,则停止
cpp
class UnionFind {
public:
bool is_connected(int a, int b) {
int fa = get_father(a);
int fb = get_father(b);
if (fa == fb) {
return true;
}
return false;
}
void merge(int a, int b) {
int fa = get_father(a);
int fb = get_father(b);
_father[fa] = fb;
}
int get_father(int a) {
while (_father[a] != a) {
a = _father[a];
}
return a;
}
void add(int a) {
if (_father.find(a) == _father.end()) {
_father[a] = a;
}
}
unordered_map<int, int> _father;
};
class Solution {
public:
struct Edge {
int a;
int b;
int cost;
Edge(int x, int y, int c) {
a = x;
b = y;
cost = c;
}
};
int dist(int x1, int y1, int x2, int y2) {
return abs(x1 - x2) + abs(y1 - y2);
}
int minCostConnectPoints(vector<vector<int>>& points) {
int len = points.size();
if (len <= 0) {
return 0;
}
UnionFind uf;
vector<Edge> edges;
for (int i = 0; i < len; ++i) {
uf.add(i);
for (int j = i + 1; j < len; ++j) {
edges.push_back(Edge(i, j,
dist(points[i][0], points[i][1], points[j][0],
points[j][1])));
}
}
sort(edges.begin(), edges.end(),
[](Edge& e1, Edge& e2) { return e1.cost < e2.cost; });
int result = 0;
int count = 0;
for (auto& e : edges) {
if (count == points.size() - 1) {
break;
}
if (uf.is_connected(e.a, e.b)) {
continue;
}
uf.merge(e.a, e.b);
result += e.cost;
++count;
}
return result;
}
};
深入解析:Leetcode 最小生成树系列(1) - yjbjingcha - 博客园
cpp
## Kruskal 算法
```java
/**
* Definition for a Connection.
* public class Connection {
* public String city1, city2;
* public int cost;
* public Connection(String city1, String city2, int cost) {
* this.city1 = city1;
* this.city2 = city2;
* this.cost = cost;
* }
* }
*/
public class Solution {
public List<Connection> lowestCost(List<Connection> connections) {
UnionFind uf = new UnionFind();
for (Connection connection : connections) {
uf.add(connection.city1);
uf.add(connection.city2);
}
int n = uf.father.size();
int m = connections.size();
Collections.sort(connections, new Comparator<Connection>() {
public int compare(Connection a, Connection b) {
if (a.cost != b.cost) {
return a.cost - b.cost;
}
if (!a.city1.equals(b.city1)) {
return a.city1.compareTo(b.city1);
}
return a.city2.compareTo(b.city2);
}
});
int edges = 0;
List<Connection> MST = new LinkedList<>();
for (Connection connection : connections) {
if (edges == n - 1) {
break;
}
if (!uf.isConnected(connection.city1, connection.city2)) {
uf.merge(connection.city1, connection.city2);
MST.add(connection);
edges += 1;
}
}
if (edges != n - 1) {
return new LinkedList<>();
}
return MST;
}
}
class UnionFind {
public Map<String, String> father;
private Map<String, Integer> sizeOfSet;
private int numOfSet = 0;
public UnionFind() {
father = new HashMap<String, String>();
sizeOfSet = new HashMap<String, Integer>();
numOfSet = 0;
}
public void merge(String x, String y) {
String rootX = find(x);
String rootY = find(y);
if (!rootX.equals(rootY)) {
father.put(rootX, rootY);
numOfSet--;
sizeOfSet.put(rootY, sizeOfSet.get(rootX) + sizeOfSet.get(rootY));
}
}
public String find(String x) {
String root = x;
while (father.get(root) != null) {
root = father.get(root);
}
while (!x.equals(root)) {
String originalFather = father.get(x);
father.put(x, root);
x = originalFather;
}
return root;
}
public void add(String x) {
if (father.containsKey(x)) {
return;
}
father.put(x, null);
sizeOfSet.put(x, 1);
numOfSet++;
}
public boolean isConnected(String x, String y) {
return find(x).equals(find(y));
}
public int getNumOfSet() {
return numOfSet;
}
public int getSizeOfSet(String x) {
return sizeOfSet.get(find(x));
}
}
```
``` python
'''
Definition for a Connection
class Connection:
def __init__(self, city1, city2, cost):
self.city1, self.city2, self.cost = city1, city2, cost
'''
class Solution:
def lowestCost(self, connections):
import functools
uf = UnionFind();
for connection in connections:
uf.add(connection.city1)
uf.add(connection.city2)
n, m = len(uf.father), len(connections)
connections.sort(key = functools.cmp_to_key(self.cmp))
edges, MST = 0, []
for connection in connections:
if edges == n - 1:
break
if not uf.is_connected(connection.city1, connection.city2):
uf.merge(connection.city1, connection.city2)
MST.append(connection)
edges += 1
if edges != n - 1:
return []
return MST
def cmp(self, a, b):
if a.cost != b.cost:
if a.cost > b.cost:
return 1
return -1
if a.city1 != b.city1:
if a.city1 > b.city1:
return 1
return -1
if a.city2 != b.city2:
if a.city2 > b.city2:
return 1
return -1
return 0
class UnionFind:
def __init__(self):
self.father = {}
self.size_of_set = {}
self.num_of_set = 0
def merge(self, x, y):
root_x, root_y = self.find(x), self.find(y)
if root_x != root_y:
self.father[root_x] = root_y
self.num_of_set -= 1
self.size_of_set[root_y] += self.size_of_set[root_x]
def find(self, x):
root = x
while self.father[root] != None:
root = self.father[root]
while x != root:
original_father = self.father[x]
self.father[x] = root
x = original_father
return root
def add(self, x):
if x in self.father:
return
self.father[x] = None
self.num_of_set += 1
self.size_of_set[x] = 1
def is_connected(self, x, y):
return self.find(x) == self.find(y)
def get_num_of_set(self):
return self.num_of_set
def get_size_of_set(self, x):
return self.size_of_set[self.find(x)]
```
## Prim 算法
```java
/**
* Definition for a Connection.
* public class Connection {
* public String city1, city2;
* public int cost;
* public Connection(String city1, String city2, int cost) {
* this.city1 = city1;
* this.city2 = city2;
* this.cost = cost;
* }
* }
*/
public class Solution {
public List<Connection> lowestCost(List<Connection> connections) {
Map<String, Integer> nameToId = new HashMap<>();
Map<Integer, String> idToName = new HashMap<>();
for (Connection connection : connections) {
if (!nameToId.containsKey(connection.city1)) {
nameToId.put(connection.city1, nameToId.size());
idToName.put(idToName.size(), connection.city1);
}
if (!nameToId.containsKey(connection.city2)) {
nameToId.put(connection.city2, nameToId.size());
idToName.put(idToName.size(), connection.city2);
}
}
int n = nameToId.size();
int[][] edges = new int[n][n];
int[][] graph = new int[n][n];
for (int i = 0; i < n; i++) {
Arrays.fill(graph[i], Integer.MAX_VALUE);
Arrays.fill(edges[i], Integer.MAX_VALUE);
}
for (Connection connection : connections) {
int start = nameToId.get(connection.city1);
int end = nameToId.get(connection.city2);
graph[start][end] = Math.min(graph[start][end], connection.cost);
graph[end][start] = Math.min(graph[end][start], connection.cost);
edges[start][end] = Math.min(edges[start][end], connection.cost);
}
List<Connection> MST = new LinkedList<>();
int[][] minDistance = new int[n][2];
Set<Integer> visited = new HashSet<>();
visited.add(0);
for (int i = 1; i < n; i++) {
minDistance[i][0] = graph[0][i];
minDistance[i][1] = 0;
}
for (int i = 1; i < n; i++) {
int cost = Integer.MAX_VALUE;
int nextNode = -1;
for (int j = 0; j < n; j++) {
if (!visited.contains(j) && cost > minDistance[j][0]) {
nextNode = j;
cost = minDistance[j][0];
}
}
if (cost == Integer.MAX_VALUE) {
return new LinkedList<>();
}
visited.add(nextNode);
int start = minDistance[nextNode][1];
int end = nextNode;
if (edges[start][end] != Integer.MAX_VALUE && edges[start][end] < edges[end][start]) {
MST.add(new Connection(idToName.get(start), idToName.get(end), cost));
}
if (edges[end][start] != Integer.MAX_VALUE && edges[end][start] < edges[start][end]) {
MST.add(new Connection(idToName.get(end), idToName.get(start), cost));
}
for (int j = 0; j < n; j++) {
if (!visited.contains(j) && minDistance[j][0] > graph[nextNode][j]) {
minDistance[j][0] = graph[nextNode][j];
minDistance[j][1] = nextNode;
}
}
}
Collections.sort(MST, new Comparator<Connection>() {
public int compare(Connection a, Connection b) {
if (a.cost != b.cost) {
return a.cost - b.cost;
}
if (!a.city1.equals(b.city1)) {
return a.city1.compareTo(b.city1);
}
return a.city2.compareTo(b.city2);
}
});
return MST;
}
}
```
``` python
'''
Definition for a Connection
class Connection:
def __init__(self, city1, city2, cost):
self.city1, self.city2, self.cost = city1, city2, cost
'''
class Solution:
def cmp(self, a, b):
if a.cost != b.cost:
if a.cost > b.cost:
return 1
return -1
if a.city1 != b.city1:
if a.city1 > b.city1:
return 1
return -1
if a.city2 != b.city2:
if a.city2 > b.city2:
return 1
return -1
return 0
def lowestCost(self, connections):
import functools
name_to_id, id_to_name = {}, {}
for connection in connections:
if connection.city1 not in name_to_id:
name_to_id[connection.city1] = len(name_to_id)
id_to_name[len(id_to_name)] = connection.city1
if connection.city2 not in name_to_id:
name_to_id[connection.city2] = len(name_to_id)
id_to_name[len(id_to_name)] = connection.city2
n = len(name_to_id)
graph = [[float("inf")] * n for _ in range(n)]
edges = [[float("inf")] * n for _ in range(n)]
for connection in connections:
start = name_to_id[connection.city1]
end = name_to_id[connection.city2]
graph[start][end] = min(graph[start][end], connection.cost)
graph[end][start] = min(graph[end][start], connection.cost)
edges[start][end] = min(edges[start][end], connection.cost)
mst, min_distance = [], [(0, 0)] * n
visited = set([0])
for i in range(1, n):
min_distance[i] = (graph[0][i], 0)
for i in range(1, n):
cost, next_node = float("inf"), -1
for j in range(n):
if j not in visited and cost > min_distance[j][0]:
next_node = j
cost = min_distance[j][0]
if cost == float("inf"):
return []
visited.add(next_node)
start, end = min_distance[next_node][1], next_node
if edges[start][end] != float("inf") and edges[start][end] < edges[end][start]:
mst.append(Connection(id_to_name.get(start), id_to_name.get(end), cost))
if edges[end][start] != float("inf") and edges[end][start] < edges[start][end]:
mst.append(Connection(id_to_name.get(end), id_to_name.get(start), cost))
for j in range(n):
if j not in visited and min_distance[j][0] > graph[next_node][j]:
min_distance[j] = (graph[next_node][j], next_node)
mst.sort(key = functools.cmp_to_key(self.cmp))
return mst
```
