Problem:
Score : 200 points

Problem Statement

Snuke is having a barbeque party.

At the party, he will make N servings of Skewer Meal.

Example of a serving of Skewer Meal

He has a stock of 2N skewers, all of which will be used in Skewer Meal. The length of the i-th skewer is L_i.
Also, he has an infinite supply of ingredients.

To make a serving of Skewer Meal, he picks 2 skewers and threads ingredients onto those skewers.
Let the length of the shorter skewer be x, then the serving can hold the maximum of x ingredients.

What is the maximum total number of ingredients that his N servings of Skewer Meal can hold, if he uses the skewers optimally?

Constraints

1≦N≦100

1≦L_i≦100

For each i, L_i is an integer.

Input

The input is given from Standard Input in the following format:

N
L_1 L_2 ... L_{2N}

Output

Print the maximum total number of ingredients that Snuke's N servings of Skewer Meal can hold.

Sample Input 1

2
1 3 1 2

Sample Output 1

3

If he makes a serving using the first and third skewers, and another using the second and fourth skewers, each serving will hold 1 and 2 ingredients, for the total of 3.

Sample Input 2

5
100 1 2 3 14 15 58 58 58 29

Sample Output 2

135

Solution in C# (Mono 4.6.2.0) (judge verdict: Runtime Error)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var str = Console.ReadLine().Split();
            var n = Int32.Parse(str[0]);
            var k = Int32.Parse(str[1]);

            var graph = new bool[n, n];
            for (int i = 0; i < n-1; i++)
            {
                str = Console.ReadLine().Split();
                var a = Int32.Parse(str[0]) - 1;
                var b = Int32.Parse(str[1]) - 1;
                graph[a, b] = true;
                graph[b, a] = true;
            }

            Console.WriteLine(Solver.Solve(n, k, graph));
        }
    }

    public class Solver
    {
        static int _n;
        static List<List<int>> _nodes;

        static HashSet<int>[] dp;

        public static int Solve(int n, int k, bool[,] graph)
        {
            _n = n;

            _nodes = new List<List<int>>();
            for (int i = 0; i < n; i++)
            {
                var l = new List<int>();
                for (int j = 0; j < _n; j++)
                {
                    if (graph[i, j]) l.Add(j);
                }
                _nodes.Add(l);
            }

            var ret = Int32.MaxValue;
            dp = new HashSet<int>[n];

            if (k % 2 == 0)
            {
                for (int i = 0; i < _n; i++)
                {
                    if (k % 2 == 0)
                    {
                        var tgtNodes = GetFarNodes(i, k / 2);
                        ret = Math.Min(ret, tgtNodes.Count());
                    }
                }
            }
            else
            {
                var used = new bool[n, n];
                for (int i = 0; i < _n; i++)
                {
                    foreach (var j in _nodes[i])
                    {
                        if (used[i, j]) continue;
                        var tgtNodesI = GetFarNodes(i, k / 2);
                        var tgtNodesJ = GetFarNodes(j, k / 2);
                        ret = Math.Min(ret, tgtNodesI.Intersect(tgtNodesJ).Count());
                        used[i, j] = true;
                    }
                }
            }

            return ret;
        }


        static HashSet<int> GetFarNodes(int idx, int dist)
        {
            if (dp[idx] != null) return dp[idx];

            var visit = new bool[_n];
            var ret = new HashSet<int>();
            Dfs(visit, ret, idx, 0, dist);

            dp[idx] = ret;
            return ret;
        }

        static void Dfs(bool[] visit, HashSet<int> ret, int idx, int currentDist, int maxDist)
        {
            if (visit[idx]) return;
            visit[idx] = true;

            if (currentDist > maxDist) ret.Add(idx);
            foreach(var next in _nodes[idx])
            {
                if (next == idx) continue;
                if (visit[next]) continue;
                Dfs(visit, ret, next, currentDist + 1, maxDist);
            }
        }
    }
}