Problem:
Score : 100 points

Problem Statement

You are given a grid of N rows and M columns. The square at the i-th row and j-th column will be denoted as (i,j).
A nonnegative integer A_{i,j} is written for each square (i,j).

You choose some of the squares so that each row and column contains at most K chosen squares.
Under this constraint, calculate the maximum value of the sum of the integers written on the chosen squares.
Additionally, calculate a way to choose squares that acheives the maximum.

Constraints

1 \leq N \leq 50

1 \leq K \leq N

0 \leq A_{i,j} \leq 10^9

All values in Input are integer.

Input

Input is given from Standard Input in the following format:

N K
A_{1,1} A_{1,2} \cdots A_{1,N}
A_{2,1} A_{2,2} \cdots A_{2,N}
\vdots
A_{N,1} A_{N,2} \cdots A_{N,N}

Output

On the first line, print the maximum value of the sum of the integers written on the chosen squares.

On the next N lines, print a way that achieves the maximum.

Precisely, output the strings t_1,t_2,\cdots,t_N, that satisfies t_{i,j}=X if you choose (i,j) and t_{i,j}=. otherwise.

You may print any way to choose squares that maximizes the sum.

Sample Input 1

3 1
5 3 2
1 4 8
7 6 9

Sample Output 1

19
X..
..X
.X.

Sample Input 2

3 2
10 10 1
10 10 1
1 1 10

Sample Output 2

50
XX.
XX.
..X

Solution in C# (.NET Core 3.1.201) (judge verdict: Accepted)

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace AtCoderLibraryCSharp.Examples
{
    public static class Program
    {
        public static void Main()
        {
            var NK = Console.ReadLine().Split(" ").Select(int.Parse).ToArray();
            var (N, K) = (NK[0], NK[1]);
            var A = new long[N][].Select(x =>
                    Console.ReadLine().Split(" ").Select(long.Parse).ToArray())
                .ToArray();
            var mcfg = new MinCostFlowGraph(N * 2 + 2);
            var s = N * 2;
            var t = N * 2 + 1;
            const long inf = (long) 1e9;
            mcfg.AddEdge(s, t, N * K, inf);
            for (var i = 0; i < N; i++)
            {
                mcfg.AddEdge(s, i, K, 0);
                mcfg.AddEdge(N + i, t, K, 0);
            }

            for (var i = 0; i < N; i++)
            for (var j = 0; j < N; j++)
                mcfg.AddEdge(i, N + j, 1, inf - A[i][j]);

            var result = mcfg.Flow(s, t, N * K);
            Console.WriteLine(inf * N * K - result.Item2);

            var G = new char[N][].Select(x => Enumerable.Repeat('.', N).ToArray()).ToArray();
            foreach (var edge in mcfg.GetEdges().Where(x => x.From != s && x.To != t && x.Flow != 0))
                G[edge.From][edge.To - N] = 'X';

            Console.WriteLine(string.Join("\n", G.Select(x => new string(x))));
        }
    }
}

namespace AtCoderLibraryCSharp
{
    public class MinCostFlowGraph
    {
        public readonly struct Edge
        {
            public readonly int From;
            public readonly int To;
            public readonly long Capacity;
            public readonly long Flow;
            public readonly long Cost;

            public Edge(int from, int to, long capacity, long flow, long cost)
            {
                From = from;
                To = to;
                Capacity = capacity;
                Flow = flow;
                Cost = cost;
            }
        }

        private readonly struct InternalEdge
        {
            public readonly int To;
            public readonly int Rev;
            public readonly long Capacity;
            public readonly long Cost;

            public InternalEdge(int to, int rev, long capacity, long cost)
            {
                To = to;
                Rev = rev;
                Capacity = capacity;
                Cost = cost;
            }
        }

        private readonly struct Q : IComparable<Q>
        {
            public readonly long Key;
            public readonly int To;

            public Q(long key, int to)
            {
                Key = key;
                To = to;
            }

            public int CompareTo(Q other)
            {
                var ret = Comparer<long>.Default.Compare(Key, other.Key);
                if (ret == 0) ret = Comparer<int>.Default.Compare(To, other.To);
                return ret;
            }
        }

        private readonly int _n;
        private readonly List<InternalEdge>[] _edges;
        private readonly List<(int X, int Y)> _pos;

        public MinCostFlowGraph(int n = 0)
        {
            _n = n;
            _edges = new List<InternalEdge>[n].Select(x => new List<InternalEdge>()).ToArray();
            _pos = new List<(int X, int Y)>();
        }

        public int AddEdge(int from, int to, long capacity, long cost)
        {
            if (from < 0 || _n <= from) throw new IndexOutOfRangeException(nameof(from));
            if (to < 0 || _n <= to) throw new IndexOutOfRangeException(nameof(to));
            var m = _pos.Count;
            _pos.Add((from, _edges[from].Count));
            _edges[from].Add(new InternalEdge(to, _edges[to].Count, capacity, cost));
            _edges[to].Add(new InternalEdge(from, _edges[from].Count - 1, 0, -cost));
            return m;
        }

        public Edge GetEdge(int i)
        {
            if (i < 0 || _pos.Count <= i) throw new IndexOutOfRangeException(nameof(i));
            var e = _edges[_pos[i].X][_pos[i].Y];
            var re = _edges[e.To][e.Rev];
            return new Edge(_pos[i].X, e.To, e.Capacity + re.Capacity, re.Capacity, e.Cost);
        }

        public IEnumerable<Edge> GetEdges()
        {
            for (var i = 0; i < _pos.Count; i++) yield return GetEdge(i);
        }

        public (long, long) Flow(int s, int t) => Flow(s, t, long.MaxValue);

        public (long, long) Flow(int s, int t, long flowLimit) => Slope(s, t, flowLimit).First();

        public IEnumerable<(long, long)> Slope(int s, int t) => Slope(s, t, long.MaxValue);

        public IEnumerable<(long, long)> Slope(int s, int t, long flowLimit)
        {
            if (s < 0 || _n <= s) throw new IndexOutOfRangeException(nameof(s));
            if (t < 0 || _n <= t) throw new IndexOutOfRangeException(nameof(t));
            if (s == t) throw new ArgumentException();
            var dual = new long[_n];
            int[] pv;
            int[] pe;

            bool Bfs()
            {
                var dist = Enumerable.Repeat(long.MaxValue, _n).ToArray();
                var visited = new bool[_n];
                pv = Enumerable.Repeat(-1, _n).ToArray();
                pe = Enumerable.Repeat(-1, _n).ToArray();
                var queue = new PriorityQueue<Q>();
                dist[s] = 0;
                queue.Enqueue(new Q(0, s));
                while (queue.Any())
                {
                    var cur = queue.Dequeue();
                    var v = cur.To;
                    if (visited[v]) continue;
                    visited[v] = true;
                    if (v == t) break;
                    for (var i = 0; i < _edges[v].Count; i++)
                    {
                        var e = _edges[v][i];
                        if (visited[e.To] || e.Capacity <= 0) continue;
                        var c = e.Cost - dual[e.To] + dual[v];
                        if (dist[e.To] <= dist[v] + c) continue;
                        dist[e.To] = dist[v] + c;
                        pv[e.To] = v;
                        pe[e.To] = i;
                        queue.Enqueue(new Q(dist[e.To], e.To));
                    }
                }

                if (!visited[t]) return false;
                for (var v = 0; v < _n; v++)
                {
                    if (!visited[v]) continue;
                    dual[v] -= dist[t] - dist[v];
                }

                return true;
            }

            var (flow, cost, prev) = (0L, 0L, -1L);
            var ret = new Stack<(long, long)>();
            ret.Push((flow, cost));
            while (flow < flowLimit && Bfs())
            {
                var c = flowLimit - flow;
                for (var v = t; v != s; v = pv[v])
                {
                    c = System.Math.Min(c, _edges[pv[v]][pe[v]].Capacity);
                }

                for (var v = t; v != s; v = pv[v])
                {
                    var e = _edges[pv[v]][pe[v]];
                    _edges[pv[v]][pe[v]] = new InternalEdge(e.To, e.Rev, e.Capacity - c, e.Cost);
                    var re = _edges[v][e.Rev];
                    _edges[v][e.Rev] = new InternalEdge(re.To, re.Rev, re.Capacity + c, re.Cost);
                }

                var d = -dual[s];
                flow += c;
                cost += c * d;
                if (prev == d) ret.Pop();
                ret.Push((flow, cost));
                prev = cost;
            }

            return ret;
        }
    }
}

namespace AtCoderLibraryCSharp
{
    public class PriorityQueue<T> : IEnumerable<T>
    {
        private readonly SortedDictionary<T, int> _data;

        public PriorityQueue() : this(null, null)
        {
        }

        public PriorityQueue(IComparer<T> comparer = null)
            : this(null, comparer)
        {
        }

        public PriorityQueue(int count, IComparer<T> comparer = null)
            : this(Enumerable.Repeat(default(T), count), comparer)
        {
        }

        public PriorityQueue(IEnumerable<T> data = null, IComparer<T> comparer = null)
        {
            comparer ??= Comparer<T>.Default;
            var list = data?.ToList() ?? new List<T>();
            var dict = new Dictionary<T, int>();
            foreach (var val in list)
            {
                if (!dict.ContainsKey(val)) dict[val] = 0;
                dict[val]++;
            }

            _data = new SortedDictionary<T, int>(dict, comparer);
        }

        public void Enqueue(T item)
        {
            if (!_data.ContainsKey(item)) _data[item] = 0;
            _data[item]++;
        }

        public T Dequeue()
        {
            if (!_data.Any()) throw new InvalidOperationException();
            var key = Peek();
            if (_data[key] > 1) _data[key]--;
            else _data.Remove(key);
            return key;
        }

        public T Peek()
        {
            if (!_data.Any()) throw new InvalidOperationException();
            using var e = _data.GetEnumerator();
            e.MoveNext();
            var (ret, _) = e.Current;
            return ret;
        }

        public bool TryDequeue(out T result)
        {
            if (_data.Any())
            {
                result = Dequeue();
                return true;
            }

            result = default;
            return false;
        }

        public bool TryPeek(out T result)
        {
            if (_data.Any())
            {
                result = Peek();
                return true;
            }

            result = default;
            return false;
        }

        public void Clear() => _data.Clear();
        public bool Contains(T item) => _data.ContainsKey(item);

        public void CopyTo(T[] array, int arrayIndex)
        {
            GetFlatData().ToList().CopyTo(array, arrayIndex);
        }

        public IEnumerator<T> GetEnumerator() => GetFlatData().GetEnumerator();
        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

        private IEnumerable<T> GetFlatData() => _data.SelectMany(x => Enumerable.Repeat(x.Key, x.Value));
    }
}