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 Ruby (2.7.1) (judge verdict: Accepted)

class Heap 
    def initialize(&block) 
        @arr = [nil]
        @fac = block
        @len = 0
    end

    def enque(x)
        @len += 1
        @arr << x
        i = @len
        while i > 1 && !@fac.call(@arr[i/2], @arr[i])
            @arr[i], @arr[i/2] = @arr[i/2], @arr[i]
            i /= 2
        end
    end

    def deque
        if @len == 0
            return nil
        elsif @len == 1
            @len = 0
            return @arr.pop
        else
            x = @arr[1]
            @arr[1] = @arr.pop
            @len -= 1
            
            i = 1
            while i*2 <= @len
                j = i*2 == @len || @fac.call(@arr[i*2], @arr[i*2+1]) ? i*2 : i*2+1
                break if @fac.call(@arr[i], @arr[j])
                @arr[i], @arr[j] = @arr[j], @arr[i]
                i = j
            end

            return x
        end
    end
end


class MCF_Graph
    Edge = Struct.new(:to, :rev, :cap, :cost)

    def initialize(n)
        @n = n
        @pos = []
        @g = Array.new(n) {[]}
        @pv = Array.new(n)
        @pe = Array.new(n)
        @dual = Array.new(n, 0)
    end

    def add_edge(from, to, cap, cost)
        m = @pos.size
        @pos << [from, @g[from].size]
        @g[from] << Edge.new(to, @g[to].size, cap, cost)
        @g[to] << Edge.new(from, @g[from].size - 1, 0, -cost)
        return m
    end

    def get_edge(i)
        _e = @g[@pos[i][0]][@pos[i][1]]
        _re = @g[_e.to][_e.rev]
        return [@pos[i][0], _e.to, _e.cap + _re.cap, _re.cap, _e.cost]
    end

    def edges
        result = []
        @pos.size.times {|i| result << get_edge(i)}
        return result
    end

    def flow(s, t, flow_limit = Float::MAX)
        return slope(s, t, flow_limit).last
    end

    def dual_ref(s, t)
        dist = Array.new(@n, Float::MAX)
        @pv.fill(-1)
        @pe.fill(-1)
        vis = Array.new(@n, false)
    
        que = Heap.new{|par, chi| par[0] < chi[0]}
        dist[s] = 0
        que.enque([0, s])
        
        while v = que.deque
            v = v[1]
    
            next if vis[v]
            vis[v] = true
            break if v == t
    
            @g[v].size.times do |i|
                e = @g[v][i]
                next if vis[e.to] || e.cap == 0
    
                cost = e.cost - @dual[e.to] + @dual[v]
                if dist[e.to] - dist[v] > cost
                    dist[e.to] = dist[v] + cost
                    @pv[e.to] = v
                    @pe[e.to] = i
                    que.enque([dist[e.to], e.to])
                end
            end
        end
    
        return false if !vis[t]
        @n.times do |v|
            next if !vis[v]
            @dual[v] -= dist[t] - dist[v]
        end
    
        return true
    end
    
    def slope(s, t, flow_limit = Float::MAX)
        flow = cost = 0
        prev_cost = -1
        result = [[flow, cost]]
    
        while flow < flow_limit
            break if !dual_ref(s, t)
            c = flow_limit - flow
            v = t
            while v != s
                c = @g[@pv[v]][@pe[v]].cap if c > @g[@pv[v]][@pe[v]].cap
                v = @pv[v]
            end
    
            v = t
            while v != s
                e = @g[@pv[v]][@pe[v]]
                e.cap -= c
                @g[v][e.rev].cap += c
                v = @pv[v]
            end
    
            d = -@dual[s]
            flow += c
            cost += c * d
            result.pop if prev_cost == d
            result << [flow, cost]
            prev_cost = cost
        end
    
        return result
    end
end

n, k = gets.split.map(&:to_i)

MAX = 10_000_000_000
m = n + n
mcf = MCF_Graph.new(m + 2)
mcf.add_edge(m, m+1, n*k, MAX)

n.times do |i|
    mcf.add_edge(m, i, k, 0)
    mcf.add_edge(n+i, m+1, k, 0)

    a = gets.split.map(&:to_i)
    a.each_with_index do |e, j|
        mcf.add_edge(i, n+j, 1, MAX - e)
    end
end

r = mcf.flow(m, m+1, n*k)
puts MAX * n * k - r[1]

ans = Array.new(n) {Array.new(n, ?.)}
mcf.edges.each do |e|
    next if e[0] >= m || e[1] >= m || e[3] == 0
    ans[e[0]][e[1] - n] = ?X
end

puts ans.map(&:join)