Problem:
Minimum Spanning Tree

Find the sum of weights of edges of the Minimum Spanning Tree for a given weighted undirected graph G = (V, E).

Input

|V| |E|
s0 t0 w0
s1 t1 w1
:
s|E|-1 t|E|-1 w|E|-1

, where |V| is the number of vertices and |E| is the number of edges in the graph. The graph vertices are named with the numbers 0, 1,..., |V|-1 respectively.

si and ti represent source and target verticess of i-th edge (undirected) and wi represents the weight of the i-th edge.

Output

Print the sum of the weights of the Minimum Spanning Tree.

Constraints

1 ≤ |V| ≤ 10,000

0 ≤ |E| ≤ 100,000

0 ≤ wi ≤ 10,000

The graph is connected

There are no parallel edges

There are no self-loops

Sample Input 1

4 6
0 1 2
1 2 1
2 3 1
3 0 1
0 2 3
1 3 5

Sample Output 1

3

Sample Input 2

6 9
0 1 1
0 2 3
1 2 1
1 3 7
2 4 1
1 4 3
3 4 1
3 5 1
4 5 6

Sample Output 2

5

Solution in C# (judge verdict: Accepted)

using System;
using System.Collections.Generic;

namespace kozaiyApp
{
    public class MinimumSpanningTree
    {
        static void Main()
        {
            string[] input = Console.ReadLine().Split(' ');
            int v = int.Parse(input[0]); // 頂点の数
            int e = int.Parse(input[1]); // 辺の数
            List<edge> edges = new List<edge>();

            for (int i = 0; i < e; i++)
            {
                string[] inputEdge = Console.ReadLine().Split(' ');
                edge edgeItem = new edge
                {
                    S = int.Parse(inputEdge[0]),
                    T = int.Parse(inputEdge[1]),
                    Cost = int.Parse(inputEdge[2])
                };
                edges.Add(edgeItem);
            }
            edges.Sort((a, b) => a.Cost - b.Cost); // Costが小さい順にソート

            int res = 0;
            UnionFind U = new UnionFind(v); // UnionFind 初期化
            for (int i = 0; i < e; i++)
            {
                edge eg = edges[i];
                if (!U.same(eg.S, eg.T)) // 同じ集合に属していない(=繋げても閉路にならない)場合のみ、木に併合する
                {
                    U.unite(eg.S, eg.T);
                    res += eg.Cost;
                }
            }

            Console.WriteLine(res);
        }


        public class edge
        {
            public int S { get; set; }
            public int T { get; set; }
            public int Cost { get; set; }
        }

        //// ---- union find ----
        public class UnionFind
        {
            int[] par; // 親
            int[] rank; // 深さ

            // n要素で初期化
            public UnionFind(int n)
            {
                par = new int[n];
                rank = new int[n];

                for (int i = 0; i < n; i++)
                {
                    par[i] = i;
                    rank[i] = 0;
                }
            }

            // 集合を併合する
            public void unite(int x, int y)
            {
                x = find(x); // xの根
                y = find(y); // yの根
                if (x == y) return;

                par[y] = x;
            }

            // 根を調べる
            public int find(int n)
            {
                if (par[n] == n)
                {
                    return n;
                }
                else
                {
                    return par[n] = find(par[n]); // 経路圧縮
                }
            }

            // xとyが同じ集合に属するか否か
            public bool same(int x, int y)
            {
                return find(x) == find(y);
            }
        }
    }
}