P3366 [Template] Minimum Spanning Tree (Kruskal)

Luogu: P3366 [Template] Minimum Spanning Tree

Insert picture description here


The minimum spanning tree solves the problem: How to use n-1 edges to connect n points with the minimum cost.
In the minimum spanning tree, we need to use and find the central find and join.


Idea: Seeking the shortest, naturally taking into account greed, first choose the shortest edge, the second short... Repeatedly select the edge with the smaller weight, until n-1 edges are selected to connect n points.

Note: During the selection process, the edges that will form the loop must be excluded.

Solution: Sort + Greedy + Union Check


Algorithm flow:

1. Sort the data by weight. We slowly add edges to discrete vertices, construct and search fa[n].

2. Select the edge (x1, y1) with the smallest weight and add it to the graph. The two endpoints (x1, y1) of this edge are selected into the minimum spanning tree, and the two vertices are connected to each other, and merge (x1, y1) in the merge check set.

3. Select the edge with the second smallest weight, first judge whether the increase of this edge constitutes a loop and whether it is in the same set: whether to add this edge, merge (xi, yi) in the merge collection; skip this edge.

4. Repeat step 3 until n-1 edges are selected to connect n points.



AC Code

It may be an edge problem. If you don’t turn on O2 optimization, the memory of the ninth example is always stuck. After turning on O2 optimization, the probability is too high.

import java.util.*;
import static java.lang.System.out;

public class Main{
    
    
    
    // 边
    static class edge implements Comparable<edge>{
    
    
        int f;
        int t;
        int c;
        public edge(int f, int t, int c){
    
    
            this.f = f;
            this.t = t;
            this.c = c;
        }
        
        public int compareTo(edge e) {
    
    
            return this.c - e.c;
        }
    }
    
    static int[] fa = new int[5007];
    
    public static int findset(int x) {
    
    
        if(x == fa[x]) return x;
        return fa[x] = findset(fa[x]);
    }
    
    public static void union(int x, int y) {
    
    
        int rootx = findset(x);
        int rooty = findset(y);
        if(rootx != rooty) fa[rootx] = rooty;
    }
    
    public static void main(String[] args) {
    
    
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int m = in.nextInt();
        edge[] e = new edge[m];
        for(int i = 0; i < m; i++) {
    
    
            int a = in.nextInt();
            int b = in.nextInt();
            int c = in.nextInt();
            // 1 <= n <= 5000
            e[i] = new edge(a - 1, b - 1, c);
        }
        // 按权值从小到大排序
        Arrays.sort(e);
        
        // 初始化
        for(int i = 0; i < n; i++) fa[i] = i;
        
        int cnt = 0, ans = 0;
        // 选 n - 1 条边将 n 个顶点连接起来就行
        for(int i = 0; i < m; i++) {
    
    

            // 已经是连通状态, 再连接就会成环
            if(findset(e[i].f) == findset(e[i].t)) continue;
            
            // 连通
            union(e[i].f, e[i].t);
            ans += e[i].c;
            cnt++;

            // 完成
            if(cnt == n - 1) {
    
    
                out.println(ans);
                return ;
            }
            
        }
        
        out.println("orz"); 
    }
    
}



Guess you like

Origin blog.csdn.net/qq_43765535/article/details/112800946