#include <bits/stdc++.h>
using namespace std;
template <class T>
bool chmax(T& a, const T& b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T>
bool chmin(T& a, const T& b) {
  if (b < a) {
    a = b;
    return 1;
  }
  return 0;
}
template <typename T>
class Grid {
  struct Pos {
    int i, j;
    Pos(int i, int j) : i(i), j(j) {}
  };
  int H, W;
  vector<vector<T>> G;
  vector<int> di8 = {1, 1, 0, -1, -1, -1, 0, 1},
              dj8 = {0, 1, 1, 1, 0, -1, -1, -1};
  vector<int> di4 = {1, 0, -1, 0}, dj4 = {0, 1, 0, -1};
  vector<Pos> neighbor(int i, int j, const vector<int>& dis,
                       const vector<int>& djs) const {
    vector<Pos> res;
    for (int k = 0; k < dis.size(); ++k) {
      if (in(i + dis[k], j + djs[k])) res.emplace_back(i + dis[k], j + djs[k]);
    }
    return res;
  }

 public:
  static bool in(int H, int W, int i, int j) {
    return 0 <= i && i < H && 0 <= j && j < W;
  }
  Grid(int H, int W) : H(H), W(W) { G.resize(H, vector<T>(W)); }
  Grid(int H, int W, T zero) : H(H), W(W) { G.resize(H, vector<T>(W, zero)); }
  vector<T>& operator[](int i) { return G[i]; }
  bool in(int i, int j) const { return (0 <= i && i < H && 0 <= j && j < W); }
  vector<Pos> neighbor8(int i, int j) const { return neighbor(i, j, di8, dj8); }
  vector<Pos> neighbor4(int i, int j) const { return neighbor(i, j, di4, dj4); }
  int to1DIndex(int i, int j) { return i * W + j; }
  Pos to2DIndex(int i) { return Pos(i / W, i % W); }
  void scanFrom(istream& strm) {
    for (int i = 0; i < (int)(H); ++i)
      for (int j = 0; j < (int)(W); ++j) strm >> G[i][j];
  }
  void outputTo(ostream& strm) {
    for (int i = 0; i < (int)(H); ++i) {
      for (int j = 0; j < (int)(W); ++j) cout << G[i][j];
      strm << endl;
    }
  }
};
template <typename T>
inline istream& operator>>(istream& strm, Grid<T>& g) {
  g.scanFrom(strm);
  return strm;
}
template <typename T>
inline ostream& operator<<(ostream& strm, Grid<T>& g) {
  g.outputTo(strm);
  return strm;
}
int n;
int X[1010][1010], Y[1010][1010];
char ans[1010][1010];
bool in(int i, int j) { return 0 <= i && i < n && 0 <= j && j < n; }
int di[4] = {1, 0, -1, 0};
int dj[4] = {0, 1, 0, -1};
int main() {
  cin >> n;
  for (int i = 0; i < (int)(n); ++i)
    for (int j = 0; j < (int)(n); ++j) {
      ans[i][j] = '?';
      scanf("%d %d", &X[i][j], &Y[i][j]);
      if (X[i][j] != -1) --X[i][j];
      if (Y[i][j] != -1) --Y[i][j];
    }
  unordered_map<int, unordered_map<int, char>> dir;
  dir[1][0] = 'D';
  dir[-1][0] = 'U';
  dir[0][1] = 'R';
  dir[0][-1] = 'L';
  function<void(int, int, int, int)> sink = [&](int i, int j, int x, int y) {
    for (int k = 0; k < (int)(4); ++k) {
      int ni = i + di[k], nj = j + dj[k];
      if (!in(ni, nj)) continue;
      if (ans[ni][nj] != '?') continue;
      if (X[ni][nj] != x || Y[ni][nj] != y) continue;
      ans[ni][nj] = dir[i - ni][j - nj];
      sink(ni, nj, x, y);
    }
  };
  for (int i = 0; i < (int)(n); ++i)
    for (int j = 0; j < (int)(n); ++j) {
      if (ans[i][j] != '?') continue;
      if (X[i][j] == -1) {
        for (int k = 0; k < (int)(4); ++k) {
          int ni = i + di[k], nj = j + dj[k];
          if (!in(ni, nj)) continue;
          if (X[ni][nj] != -1) continue;
          ans[i][j] = dir[ni - i][nj - j];
          ans[ni][nj] = dir[i - ni][j - nj];
          sink(i, j, -1, -1);
          sink(ni, nj, -1, -1);
        }
      } else {
        if (ans[X[i][j]][Y[i][j]] != '?') break;
        if (X[X[i][j]][Y[i][j]] != X[i][j] || Y[X[i][j]][Y[i][j]] != Y[i][j])
          break;
        ans[X[i][j]][Y[i][j]] = 'X';
        sink(X[i][j], Y[i][j], X[i][j], Y[i][j]);
      }
    }
  for (int i = 0; i < (int)(n); ++i)
    for (int j = 0; j < (int)(n); ++j) {
      if (ans[i][j] == '?') {
        cout << "INVALID" << endl;
        return 0;
      }
    }
  cout << "VALID" << endl;
  for (int i = 0; i < (int)(n); ++i) {
    for (int j = 0; j < (int)(n); ++j) cout << ans[i][j];
    cout << endl;
  }
  return 0;
}
