
方法一:Kruskal算法
- 依次选择权值最小的边
- 如果要加入的边会使得图形成环,则跳过
- 使用并查集来判断是否会形成环
- 如果两个顶点不在同一个子图中,连接边不会形成环
- 如果两个顶点在同一个子图中,连接边会形成环
- 恰好可以用union解决
比如有三个顶点,1,2,3那么所有的边为(1,2),(1,3),(2,3)
1
| int[][] edges = new int[n * (n - 1) / 2][3];
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| class Solution { public int minCostConnectPoints(int[][] points) { int n = points.length; int[][] edges = new int[n * (n - 1) / 2][3];
int index = 0; for (int i = 0; i < n; ++i) for (int j = i + 1; j < n; ++j) edges[index++] = new int[]{i, j, Math.abs(points[i][0] - points[j][0]) + Math.abs(points[i][1] - points[j][1])}; return kruskal(edges, n); }
private int kruskal(int[][] edges, int n) { int res = 0; init(n); Arrays.sort(edges, (o1, o2) -> Integer.compare(o1[2], o2[2])); for (int[] edge : edges) { int node1 = edge[0], node2 = edge[1]; if (union(node1, node2)) { res += edge[2]; } } return res; } int[] parent; private boolean union(int i, int j) { int rootI = findParent(i), rootJ = findParent(j); if (rootI != rootJ) { parent[rootI] = rootJ; return true; } return false; }
private int findParent(int i) { if (i != parent[i]) parent[i] = findParent(parent[i]); return parent[i]; }
private void init(int n) { parent = new int[n]; for (int i = 0; i < n; ++i) parent[i] = i; } }
|
方法二:Prim算法
误区:以下是prim,prim需要更新的是已选顶点集距离未选顶点的最短距离
1 2 3
| for (int j = 0; j < n; ++j) if (!visited[j] && dist[j] > graph[minIndex][j]) dist[j] = graph[minIndex][j];
|
以下是dijkstra
1 2 3
| for (int j = 1; j <= n; ++j) if (!visited[j] && dist[j] > graph[minIndex][j] + minDist) dist[j] = graph[minIndex][j] + minDist;
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| class Solution { public int minCostConnectPoints(int[][] points) { int n = points.length, index = 0; int[][] graph = new int[n][n]; for (int i = 0; i < n; ++i) for (int j = i + 1; j < n; ++j) graph[i][j] = graph[j][i] = getMDistance(points[i], points[j]); return prim(graph, n); }
private int prim(int[][] graph, int n) { int res = 0, inf = Integer.MAX_VALUE >> 1; int[] dist = new int[n]; boolean[] visited = new boolean[n]; for (int i = 1; i < n; ++i) dist[i] = inf; for (int i = 0; i < n; ++i) { int minIndex = -1, minDist = inf; for (int j = 0; j < n; ++j) { if (!visited[j] && dist[j] < minDist) { minDist = dist[j]; minIndex = j; } } visited[minIndex] = true; res += minDist; for (int j = 0; j < n; ++j) if (!visited[j] && dist[j] > graph[minIndex][j]) dist[j] = graph[minIndex][j]; } return res; }
public int getMDistance(int[] d1, int[] d2) { return Math.abs(d1[0] - d2[0]) + Math.abs(d1[1] - d2[1]); } }
|
