Day57--图论--53. 寻宝(卡码网) - 实践

Day57–图论–53. 寻宝(卡码网)

今天学习:最小生成树。有两种算法(Prim和Kruskal)和一道例题。

prim 算法是维护节点的集合,而 Kruskal 是维护边的集合

最小生成树:所有节点的最小连通子图,即:以最小的成本(边的权值)将图中所有节点连接到一起。

53. 寻宝(卡码网)

方法:Prim最小生成树

思路:

  1. 第一步,选距离生成树最近节点
  2. 第二步,最近节点加入生成树
  3. 第三步,更新非生成树节点到生成树的距离(即更新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);
}
}
posted @ 2025-08-16 12:12  yfceshi  阅读(9)  评论(0)    收藏  举报