import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 返回最小的花费代价使得这n户人家连接起来
     * @param n int n户人家的村庄
     * @param m int m条路
     * @param cost int二维数组 一维3个参数,表示连接1个村庄到另外1个村庄的花费的代价
     * @return int
     */
    public int miniSpanningTree (int n, int m, int[][] cost) {
        // write code here
        //常规prim是针对点来遍历,时间复杂度高,可以将边存储,
        //首先将边按照权值将边从小到大排序
        Arrays.sort(cost, Comparator.comparingInt(o -> o[2]));
        //新建一个ArrayList存储边,以便于遍历时将不会用到的边删除,即剪枝。
        ArrayList<int[]> edges = new ArrayList<>();
        for (int i = 0; i < m; i++) {
            edges.add(cost[i]);
        }
        //新建一个集合存储点,为了方便终止遍历,使用hashset
        HashSet<Integer> vers = new HashSet<>();
        vers.add(edges.get(0)[0]);
        vers.add(edges.get(0)[1]);
        int sum = edges.get(0)[2];
        //新建一个集合用来剪枝,删除不会再用的边
        ArrayList<Integer> delete = new ArrayList<>();
        while (vers.size()<n){
            for (int i = 0; i < edges.size(); i++) {
                if(vers.contains(edges.get(i)[0]) && vers.contains(edges.get(i)[1])){
                    //如果这条边的两个点都到访过了,那以后也就不用了
                    delete.add(i);
                } else if (!vers.contains(edges.get(i)[0]) && !vers.contains(edges.get(i)[1])) {
                    //啥也不做,纯粹是不想写太长的条件,排除掉这个边的两点都没访问过的情况
                } else{
                    //因为边集合已经排过序,所以遇到的第一个符合要求的就是最短的,将其设为访问,然后跳出这次循环
                    vers.add(edges.get(i)[0]);
                    vers.add(edges.get(i)[1]);
                    sum += edges.get(i)[2];
                    delete.add(i);
                    break;
                }
            }
            //将不用的边删除
            for (int i = delete.size()-1; i >= 0; i--) {
                edges.remove(delete.get(i).intValue());
            }
            delete.clear();
        }
        return sum;
    }
}