Day57--图论--53. 寻宝(卡码网)
Day57–图论–53. 寻宝(卡码网)
今天学习:最小生成树。有两种算法(Prim和Kruskal)和一道例题。
prim 算法是维护节点的集合,而 Kruskal 是维护边的集合。
最小生成树:所有节点的最小连通子图,即:以最小的成本(边的权值)将图中所有节点连接到一起。
53. 寻宝(卡码网)
方法:Prim最小生成树
思路:
- 第一步,选距离生成树最近节点
- 第二步,最近节点加入生成树
- 第三步,更新非生成树节点到生成树的距离(即更新minDist数组)(minDist数组用来记录每一个节点距离最小生成树的最近距离。)
import java.util.*;public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);int v = in.nextInt();int e = in.nextInt();int[][] grid = new int[v + 1][v + 1];for (int i = 0; i <= v; i++) {Arrays.fill(grid[i], 10001);}for (int i = 0; i < e; i++) {int from = in.nextInt();int to = in.nextInt();int val = in.nextInt();grid[from][to] = val;grid[to][from] = val;}int[] minDist = new int[v + 1];Arrays.fill(minDist, 10001);boolean[] isInTree = new boolean[v + 1];for (int i = 1; i < v; i++) {int cur = -1;int minVal = Integer.MAX_VALUE;for (int j = 1; j <= v; j++) {if (!isInTree[j] && minDist[j] < minVal) {minVal = minDist[j];cur = j;}}isInTree[cur] = true;for (int j = 1; j <= v; j++) {if (!isInTree[j] && grid[cur][j] < minDist[j]) {minDist[j] = grid[cur][j];}}}int sum = 0;for (int i = 2; i <= v; i++) {sum += minDist[i];}System.out.println(sum);}
}
方法:Kruskal最小生成树
思路:
- 边的权值排序,因为要优先选最小的边加入到生成树里
- 遍历排序后的边
- 如果边首尾的两个节点在同一个集合,说明如果连上这条边图中会出现环
- 如果边首尾的两个节点不在同一个集合,加入到最小生成树,并把两个节点加入同一个集合
import java.util.*;class Disjoint {private int[] father;public Disjoint(int n) {father = new int[n + 1];for (int i = 0; i <= n; i++) {father[i] = i;}}public int find(int a) {if (a == father[a]) {return a;} else {return father[a] = find(father[a]);}}public boolean isSame(int o1, int o2) {return find(o1) == find(o2);}public void join(int o1, int o2) {int root1 = find(o1);int root2 = find(o2);if (root1 == root2) {return;}father[root2] = root1;}
}public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);int v = in.nextInt();int e = in.nextInt();Disjoint dj = new Disjoint(v);int[][] edges = new int[e][3];for (int i = 0; i < e; i++) {edges[i][0] = in.nextInt();edges[i][1] = in.nextInt();edges[i][2] = in.nextInt();}Arrays.sort(edges, (a, b) -> Integer.compare(a[2], b[2]));int sum = 0;for (int i = 0; i < e; i++) {int n1 = edges[i][0];int n2 = edges[i][1];int val = edges[i][2];if (!dj.isSame(n1, n2)) {dj.join(n1, n2);sum += val;}}System.out.println(sum);}
}