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;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

static class MainClass
{
    private static Scanner scanner;
    public static void Main()
    {
        scanner = new Scanner();
        Solve();
        // for scanner bug
        scanner.Next();
    }

    private static void Solve()
    {
        var v = scanner.NextInt();
        var e = scanner.NextInt();
        var kruskal = new Kruskal(v);
        for (int i = 0; i < e; i++)
        {
            kruskal.AddEdge(scanner.NextInt(), scanner.NextInt(), scanner.NextInt());
        }
        kruskal.Calculate();
        Console.WriteLine(kruskal.TotalCost);
    }

    class Kruskal
    {
        public int TotalCost { get; private set; }
        private int capacity;
        private Heap<Pair2> edges;
        public Kruskal(int capacity)
        {
            edges = new Heap<Pair2>();
            this.capacity = capacity;
        }
        public void AddEdge(int from, int to, int cost)
        {
            edges.Push(new Pair2(to, from, cost));
        }
        public void Calculate()
        {
            var uf = new UnionFind(capacity);
            while (edges.Count > 0)
            {
                var item = edges.Pop();
                if (!uf.Same(item.To, item.From))
                {
                    uf.Unite(item.To, item.From);
                    TotalCost += item.Cost;
                }
            }
        }
        class UnionFind
        {
            private int[] graph;
            private int[] rank;
            public UnionFind(int capacity)
            {
                graph = new int[capacity];
                rank = new int[capacity];
                for (int i = 0; i < capacity; i++)
                {
                    graph[i] = i;
                    rank[i] = 0;
                }
            }

            public void Unite(int first, int second)
            {
                var rootX = graph[first];
                var rootY = graph[second];
                if (rootX == rootY)
                {
                    return;
                }
                if (rank[rootX] < rank[rootY])
                {
                    graph[rootX] = rootY;
                }
                else
                {
                    graph[rootY] = rootX;
                    if (rank[rootX] == rank[rootY])
                    {
                        rank[rootX]++;
                    }
                }
            }
            public bool Same(int first, int second)
            {
                return Root(first) == Root(second);
            }
            public int Root(int x)
            {
                if (graph[x] == x)
                {
                    return x;
                }
                else
                {
                    graph[x] = Root(graph[x]);
                    return graph[x];
                }
            }
        }

        struct Pair2 : IComparable<Pair2>
        {
            public int Cost { get; }
            public int To { get; }
            public int From { get; }
            public Pair2(int to, int from, int cost)
            {
                To = to;
                From = from;
                Cost = cost;
            }

            public int CompareTo(Pair2 other)
            {
                return Cost.CompareTo(other.Cost);
            }
        }
    }
    class Heap<T> where T : IComparable<T>
    {
        private readonly List<T> heapList;
        public Heap()
        {
            heapList = new List<T>();
        }
        public Heap(int capacity)
        {
            heapList = new List<T>(capacity);
        }
        public void Push(T item)
        {
            var index = heapList.Count;
            heapList.Add(item);
            while (true)
            {
                var parentInd = (index - 1) / 2;
                var parent = heapList[parentInd];
                if (parent.CompareTo(item) > 0)
                {
                    Exchange(parentInd, index);
                    index = parentInd;
                    continue;
                }
                break;
            }
        }
        public T Pop()
        {
            var lastInd = heapList.Count - 1;
            if (lastInd == 0)
            {
                var cur = heapList[0];
                heapList.RemoveAt(0);
                return cur;
            }
            else if (lastInd < 0)
            {
                throw new InvalidOperationException();
            }
            var ret = heapList[0];
            var msi = heapList[0] = heapList[lastInd];
            heapList.RemoveAt(lastInd--);
            var current = 0;
            while (true)
            {
                var child1 = current * 2 + 1;
                var child2 = current * 2 + 2;
                if (child1 > lastInd)
                {
                    return ret;
                }
                else if (child2 > lastInd)
                {
                    if (msi.CompareTo(heapList[child1]) > 0)
                    {
                        Exchange(current, child1);
                    }
                    return ret;
                }
                if (heapList[child1].CompareTo(heapList[child2]) > 0)
                {
                    if (msi.CompareTo(heapList[child2]) > 0)
                    {
                        Exchange(current, child2);
                        current = child2;
                        continue;
                    }
                }
                else
                {
                    if (msi.CompareTo(heapList[child1]) > 0)
                    {
                        Exchange(current, child1);
                        current = child1;
                        continue;
                    }
                }
                return ret;
            }

        }
        private void Exchange(int first, int second)
        {
            var sItem = heapList[second];
            heapList[second] = heapList[first];
            heapList[first] = sItem;
        }
        public int Count => heapList.Count;
    }


    private static int UpperBound<T>(this IEnumerable<T> list, T item) where T : IComparable<T> => UpperBound(list.ToList(), item);
    private static int LowerBound<T>(this IEnumerable<T> list, T item) where T : IComparable<T> => LowerBound(list.ToList(), item);

    private static int UpperBound<T>(this List<T> list, T item) where T : IComparable<T>
    {
        return list.BinarySearch(item, -1, list.Count, (first, second) => first.CompareTo(second) > 0);
    }

    private static int LowerBound<T>(this List<T> list, T item) where T : IComparable<T>
    {
        return list.BinarySearch(item, -1, list.Count, (first, second) => first.CompareTo(second) >= 0);
    }

    private static int BinarySearch<T>(this List<T> list, T item, int left, int right, Func<T, T, bool> isOkPredicate)
    {
        while (Math.Abs(right - left) > 1)
        {
            var mid = left + (right - left) / 2;
            if (isOkPredicate(list[mid], item))
            {
                right = mid;
            }
            else
            {
                left = mid;
            }
        }
        return right;
    }


    #region ライブラリ

    public static long ToInt64(this string str) => long.Parse(str);
    public static bool IsInt32(this string str)
    {
        var o = 0;
        return int.TryParse(str, out o);
    }
    public static int ToInt32(this string str) => str == "" ? 0 : int.Parse(str);
    public static double ToDouble(this string str) => double.Parse(str);
    public static BigInteger ToBigInteger(this string str) => BigInteger.Parse(str);
    public static List<string> SplittedStringToList(this string str) => str.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList();
    public static List<int> SplittedStringToInt32List(this string str) => str.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Select(x => int.Parse(x)).ToList();
    public static List<long> SplittedStringToInt64List(this string str) => str.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Select(x => long.Parse(x)).ToList();
    public static List<BigInteger> SplittedStringToBigInteger(this string str) => str.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Select(x => BigInteger.Parse(x)).ToList();
    public const int INF = int.MaxValue / 4;
    public const long LONGINF = long.MaxValue / 2;
    public const int Mod1e9 = 1000000007;
    public static List<int> ToCumulativeSumList(this List<int> list)
    {
        var ls = new List<int>
        {
            list[0]
        };
        var count = list.Count;
        for (int i = 1; i < count; i++)
        {
            ls.Add(list[i] + ls.Last());
        }
        return ls;
    }

    public static void PrintArray(long[,] array)
    {
        for (int i = 0; i < array.GetLength(0); i++)
        {
            var sb = new StringBuilder();
            for (int j = 0; j < array.GetLength(1); j++)
            {
                sb.Append(array[i, j]).Append(" ");
            }
            Console.WriteLine(sb.ToString().Trim());
        }
    }
    public static int Manhattan(int x1, int x2, int y1, int y2)
    {
        return Math.Abs(x1 - x2) + Math.Abs(y1 - y2);
    }

    public static int Manhattan(KeyValuePair<int, int> keyValuePair1, KeyValuePair<int, int> keyValuePair2)
    {
        return Manhattan(keyValuePair1.Key, keyValuePair2.Key, keyValuePair1.Value, keyValuePair2.Value);
    }

    public static T DeepClone<T>(this T src)
    {
        var memoryStream = new MemoryStream();
        var binaryFormatter = new BinaryFormatter();
        binaryFormatter.Serialize(memoryStream, src);
        memoryStream.Seek(0, SeekOrigin.Begin);
        memoryStream.Dispose();

        return (T)binaryFormatter.Deserialize(memoryStream);
    }

    public static Dictionary<T, int> ToCountedDictionary<T>(this IEnumerable<T> items)
    {
        var dic = new Dictionary<T, int>();
        foreach (var item in items)
        {
            if (dic.ContainsKey(item))
                dic[item]++;
            else
                dic.Add(item, 1);
        }
        return dic;
    }
    public static Dictionary<TKey, TValue> KeyValuePairListToDictionary<TKey, TValue>(this IEnumerable<KeyValuePair<TKey, TValue>> pairs)
    {
        var dic = new Dictionary<TKey, TValue>();
        foreach (var item in pairs)
        {
            dic.Add(item.Key, item.Value);
        }
        return dic;
    }
    public class Scanner
    {
        private readonly TextReader reader;
        public Scanner()
        {
            reader = Console.In;
        }
        public Scanner(TextReader reader)
        {
            this.reader = reader;
        }
        private string NextWord()
        {
            var sb = new StringBuilder();
            while (true)
            {
                var c = reader.Read();
                if ((c == 13 || c == 10 || c == 32) && sb.Length > 0 || c == -1)
                {
                    break;
                }
                sb.Append((char)c);
            }
            return sb.ToString().Trim();
        }
        public int NextInt() => NextWord().ToInt32();
        public string Next() => NextWord();
        public double NextDouble() => NextWord().ToDouble();
        public long NextLong() => NextWord().ToInt64();
        public BigInteger NextBigInteger() => NextWord().ToBigInteger();
        public string NextLine()
        {
            var str = reader.ReadLine();
            if (string.IsNullOrWhiteSpace(str))
            {
                return reader.ReadLine();
            }
            else
            {
                return str;
            }
        }
        private List<string> NextLineToList() => NextLine().Split(new char[] { ' ' },
                                                                  StringSplitOptions.RemoveEmptyEntries)
                                                           .ToList();
        public List<int> NextLineToIntList() => NextLineToList().Select(x => int.Parse(x))
                                                                .ToList();
    }
    public static long Sums(IEnumerable<int> list)
    {
        var sum = 0L;
        foreach (var item in list)
        {
            sum += Math.Abs(item);
        }
        return sum;
    }
    public static string IEnumerableListToString<T>(this IEnumerable<T> ls, bool withSpace = false)
    {
        var sb = new StringBuilder();
        foreach (var item in ls)
        {
            sb.Append(item);
            if (withSpace)
            {
                sb.Append(" ");
            }
        }
        return sb.ToString();
    }
    #endregion

    public static int[] dx = { -1, 1, 0, 0 };
    public static int[] dy = { 0, 0, 1, -1 };

    public static int[] dxx = { 0, 1, 1, 1, 0, -1, -1, -1 };
    public static int[] dyy = { 1, 1, 0, -1, -1, -1, 0, 1 };

}