#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
#define rep(i,s,e) for(i64 (i) = (s);(i) < (e);(i)++)
#define all(x) x.begin(),x.end()
#define STRINGIFY(n) #n
#define TOSTRING(n) STRINGIFY(n)
#define PREFIX "#" TOSTRING(__LINE__) "| "
#define debug(x) \
{ \
  std::cout << PREFIX << #x << " = " << x << std::endl; \
}

std::ostream& output_indent(std::ostream& os, int ind) {
  for(int i = 0; i < ind; i++) os << " ";
  return os;
}

template<class S, class T> std::ostream& operator<<(std::ostream& os, const std::pair<S, T>& p);
template<class T> std::ostream& operator<<(std::ostream& os, const std::vector<T>& v);

template<class S, class T> std::ostream& operator<<(std::ostream& os, const std::pair<S, T>& p) {
  return (os << "(" << p.first << ", " << p.second << ")");
}
template<class T> std::ostream& operator<<(std::ostream& os, const std::vector<T>& v) {
  os << "[";
  for(int i = 0;i < v.size();i++) os << v[i] << ", ";
  return (os << "]");
}

template<class T>
static inline std::vector<T> ndvec(size_t&& n, T val) { return std::vector<T>(n, std::forward<T>(val)); }
template<class... Tail>
static inline auto ndvec(size_t&& n, Tail&&... tail) {
  return std::vector<decltype(ndvec(std::forward<Tail>(tail)...))>(n, ndvec(std::forward<Tail>(tail)...));
}
template<class Cond> struct chain {
  Cond cond; chain(Cond cond) : cond(cond) {}
  template<class T> bool operator()(T& a, const T& b) const { if(cond(a, b)) { a = b; return true; } return false; }
};
template<class Cond> chain<Cond> make_chain(Cond cond) { return chain<Cond>(cond); }

#include <vector>
#include <algorithm>
#include <queue>
#include <numeric>

struct capacity_scaling_ssp_mcf {
  using capacity_type = long long;
  using weight_type = long long;
  using size_type = std::size_t;


  struct edge {
    size_type to;
    size_type rev;
    capacity_type cap;
    capacity_type flow;
    weight_type weight;
    capacity_type residual_cap() const {
      return cap - flow;
    }
  };

  struct edge_ptr {
    size_type from;
    size_type idx;
  };

  size_type n;
  std::vector<std::vector<edge>> g;
  std::vector<capacity_type> b;
  std::vector<weight_type> phi;

  capacity_scaling_ssp_mcf(size_type n)
    : n(n),
      g(n),
      b(n),
      phi(n) {
  }

  edge_ptr add_edge(size_type from, size_type to, capacity_type lower, capacity_type upper, weight_type weight) {
    size_type fidx = g[from].size();
    size_type tidx = g[to].size() + !!(from == to);
    g[from].push_back(edge { to, tidx, upper, capacity_type(0), weight });
    g[to].push_back(edge { from, fidx, -lower, capacity_type(0), -weight });
    return edge_ptr { from, fidx };
  }

  void add_supply(size_type v, const capacity_type& amount) {
    b[v] += amount;
  }

  void add_demand(size_type v, const capacity_type& amount) {
    b[v] -= amount;
  }

  const capacity_type& get_edge_flow(const edge_ptr& e) {
    return g[e.from][e.idx].flow;
  }

  const weight_type& get_potential(size_type v) {
    return phi[v];
  }

private:

  capacity_type get_delta(const capacity_type& scaling_factor) const {
    capacity_type cap_inf = *std::max_element(std::begin(b), std::end(b));
    for(const auto& es: g) for(const auto& e: es) {
      cap_inf = std::max({ cap_inf, e.cap, -e.cap });
    }
    capacity_type delta = capacity_type(1);
    while(delta < cap_inf) { delta *= scaling_factor; }
    return delta;
  }

  void push(edge& e, const capacity_type& amount) {
    e.flow += amount;
    g[e.to][e.rev].flow -= amount;
  }

  weight_type residual_weight(size_type from, const edge& e) const {
    return e.weight + phi[from] - phi[e.to];
  }

  void saturate_negative(const capacity_type& delta) {
    for(size_type v = 0; v < n; v++) {
      for(auto& e: g[v]) {
        capacity_type cap = e.residual_cap();
        cap -= cap % delta;
        if(cap < 0 || residual_weight(v, e) < 0) {
          push(e, cap);
          b[v] -= cap;
          b[e.to] += cap;
        }
      }
    }
  }

  void dual(size_type excess_cnt, const std::vector<size_type>& excess_vs, const capacity_type& delta, std::vector<edge_ptr>& par, std::vector<size_type>& dificit_vs) {
    using P = std::pair<weight_type, size_type>;
    std::priority_queue<P, std::vector<P>, std::greater<P>> que;
    std::vector<weight_type> dist(n, std::numeric_limits<weight_type>::max());
    weight_type farthest = 0;
    for(size_type i = 0; i < excess_cnt; i++) {
      size_type v = excess_vs[i];
      dist[v] = 0;
      que.emplace(dist[v], v);
    }
    while(!que.empty()) {
      weight_type d = que.top().first;
      size_type v = que.top().second;
      que.pop();
      if(dist[v] < d) continue;
      farthest = d;
      if(b[v] <= -delta) dificit_vs.push_back(v);
      for(size_type ei = 0; ei < g[v].size(); ei++) {
        const auto& e = g[v][ei];
        if(e.residual_cap() < delta) continue;
        weight_type wgh = d + residual_weight(v, e);
        if(dist[e.to] > wgh) {
          dist[e.to] = wgh;
          par[e.to] = edge_ptr { v, ei };
          que.push({ wgh, e.to });
        }
      }
    }
    for(size_type i = 0; i < n; i++) {
      phi[i] += std::min(dist[i], farthest);
    }
  }

  void primal(const std::vector<edge_ptr>& par, const std::vector<size_type>& dificit_vs, const capacity_type& delta) {
    for(const auto& t: dificit_vs) {
      capacity_type f = -b[t];
      size_type v = t;
      while(par[v].idx != std::numeric_limits<size_type>::max()) {
        f = std::min(f, g[par[v].from][par[v].idx].residual_cap());
        v = par[v].from;
      }
      f = std::min(f, b[v]);
      f -= f % delta;
      if(f <= 0) continue;
      v = t;
      while(par[v].idx != std::numeric_limits<size_type>::max()) {
        push(g[par[v].from][par[v].idx], f);
        v = par[v].from;
      }
      b[t] += f;
      b[v] -= f;
    }
  }
  bool remove_not_excess(std::vector<size_type>& excess_vs, size_type& excess_cnt, const capacity_type& delta) {
    for(size_type i = 0; i < excess_cnt;) {
      if(b[excess_vs[i]] < delta) {
        std::swap(excess_vs[i], excess_vs[--excess_cnt]);
      }
      else {
        i++;
      }
    }
    return excess_cnt > 0;
  }
public:
  bool solve(const capacity_type& scaling_factor) {
    std::vector<size_type> excess_vs(n);
    size_type excess_cnt;
    std::vector<size_type> dificit_vs;
    dificit_vs.reserve(n);
    std::vector<edge_ptr> par(n);
    for(capacity_type delta = get_delta(scaling_factor);
        delta > 0;
        delta /= scaling_factor) {
      std::iota(std::begin(excess_vs), std::end(excess_vs), 0);
      excess_cnt = n;
      saturate_negative(delta);
      while(remove_not_excess(excess_vs, excess_cnt, delta)) {
        dificit_vs.clear();
        std::fill(std::begin(par), std::end(par), edge_ptr { 0, std::numeric_limits<size_type>::max() });
        dual(excess_cnt, excess_vs, delta, par, dificit_vs);
        if(dificit_vs.size() > 0) {
          primal(par, dificit_vs, delta);
        }
        else {
          break;
        }
      }
    }
    return std::count(std::begin(b), std::end(b), 0) == n;
  }

  bool max_flow(size_type s, size_type t, capacity_type scaling_factor) {
    capacity_type inf = std::abs(b[s]);
    for(const auto& e: g[s]) inf += std::max(e.cap, capacity_type(0));
    add_edge(t, s, 0, inf, 0);
    if(!solve(scaling_factor)) {
      g[s].pop_back();
      g[t].pop_back();
      return false;
    }
    else {
    rep(i,0,n) {
      debug(i);
      debug(b[i]);
    }
      inf = std::abs(b[s]);
      for(const auto& e: g[s]) inf += e.residual_cap();
      b[s] += inf;
      b[t] -= inf;
      solve(scaling_factor);
      b[s] -= inf;
      b[t] += inf;
      g[s].pop_back();
      g[t].pop_back();
      return true;
    }

  }

  template<class Cost>
  Cost get_result() const {
    Cost result = 0;
    for(const auto& es: g) for(const auto& e: es) {
      result += Cost(e.flow) * Cost(e.weight);
    }
    return result / 2;
  }
};

#include <unistd.h>

namespace niu {

  struct fastin {
    static const int bufsize = 1 << 24;
    char buf[bufsize];
    char* iter;
    fastin() {
      iter = buf;
      for(int t = 0, k; (k = read(STDIN_FILENO, buf + t, sizeof(buf)) - t) > 0; t += k);
    }
    fastin& operator>>(int& num) {
      num = 0;
      bool neg = false;
      while(*iter < '+') iter++;
      if(*iter == '-') { neg = true; iter++; }
      else if(*iter == '+') iter++;
      while(*iter >= '0') num = 10 * num + *(iter++) - '0';
      if(neg) num = -num;
      return *this;
    } 
  } fin;
  struct fastout {
    static const int bufsize = 1 << 24;
    char buf[bufsize];
    char* iter;
    fastout() {
      iter = buf;
    }
    ~fastout() {
      for(int t = 0, k; (k = write(STDOUT_FILENO, buf + t, iter - buf - t)) > 0; t += k);
    }
    fastout& operator<<(i64 num) {
      static char tmp[20];
      if(num == 0) {
        *(iter++) = '0';
        return *this;
      }
      if(num < 0) {
        *(iter++) = '-';
        num = -num;
      }
      int i = 0;
      while(num) {
        tmp[i++] = num % 10;
        num /= 10;
      }
      while(i--) {
        *(iter++) = tmp[i] + '0';
      }
      return *this;
    }
    fastout& operator<<(char c) {
      *(iter++) = c;
      return *this;
    }
  } fout;
}

int main() {
  using niu::fin;
  using niu::fout;
  int N, K;
  fin >> N >> K;
  capacity_scaling_ssp_mcf mcf(2 + N + N);
  int s = N + N;
  int t = N + N + 1;
  const long long INF = 1e9;
  rep(i,0,N) {
    mcf.add_edge(s, i, 0, K, 0);
    mcf.add_edge(N + i, t, 0, K, 0);
  }
  rep(i,0,N) {
    rep(j,0,N) {
      int a;
      fin >> a;
      mcf.add_edge(i, N + j, 0, 1, INF - a);
    }
  }
  mcf.add_edge(s, t, 0, N * N, INF);
  mcf.add_supply(s, N * N);
  mcf.add_demand(t, N * N);
  mcf.solve(2);
  i64 res = 0;
  string ans(N * (N + 1), '.');
  rep(i,0,N) ans[i * (N + 1) + N] = '\n';
  rep(i,0,N) {
    for(const auto& e: mcf.g[i]) {
      if(N <= e.to && e.flow == 1) {
        ans[i * (N + 1) + e.to - N] = 'X';
        res += INF - e.weight;
      }
    }
  }
  fout << res << '\n';
  for(char c: ans) fout << c;
}


Measured memory_bytes: 3852