最小生成树——kruskal算法(并查集)

思路:先把边按照权值进行排序,用贪心的思想优先选取权值较小的边,并依次连接,若出现环则跳过此边(用并查集来判断是否存在环)继续搜,直到已经使用的边的数量比总点数少一即可。

模板题目传送门:

P3366 【模板】最小生成树 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.Arrays;

public class Kruskal {
    static int[] f; 

    public static void main(String[] args) throws IOException {
        PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
        StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));

        in.nextToken();
        int n = (int)in.nval;
        in.nextToken();
        int m = (int)in.nval;

        Edge[] e = new Edge[m + 1];
        for(int i = 1; i <= m; ++i) {
            e[i] = new Edge();
            in.nextToken();
            e[i].u = (int)in.nval;
            in.nextToken();
            e[i].v = (int)in.nval;
            in.nextToken();
            e[i].w = (int)in.nval;
        }

        //按边权排序(升序)
        Arrays.sort(e, 1, m + 1, (a,b)-> {
            return a.w - b.w;
        });

        f = new int[10005];
        int ans = 0;
        int k = 1;
        
        //并查集初始化
        for (int i = 1; i <= n; i++) f[i] = i;

        for(int i = 1; i <= m; ++i) {
            int l = find(e[i].u);
            int r = find(e[i].v);
            if (l != r) {    //若两点未联通则联合
                f[r] = l;
                ans += e[i].w;    //累加权值
                ++k;    //已连接点+1
                if (k == n) {
                    break;
                }
            }
        }

        if (k == n) {
            out.println(ans);
        } else {
            out.println("orz");
        }
        out.flush();
    }

    private static int find(int x) {
        return f[x] == x ? x : (f[x] = find(f[x]));
    }
}
class Edge {
    int u,v,w;
}

时间:2022-6-16 21:21

猜你喜欢

转载自blog.csdn.net/m0_62755833/article/details/125323487