#include <bits/stdc++.h>
using namespace std;
struct edge {
  int u, v, cost;
  bool operator<(const edge &d) const { return cost < d.cost; }
};
int parent[2010], matrix[2010][2010], dist[2010][2010], visited[2010];
vector<int> A[2010], W[2010];
vector<edge> E;
void _visit() {
  for (int i = 0; i < 2010; i++) visited[i] = false;
}
int f(int u) { return parent[u] = parent[u] == u ? u : f(parent[u]); }
bool _unite(int i, int j) {
  int u = f(i), v = f(j);
  if (u == v) return false;
  parent[u] = v;
  return true;
}
void dfs(int p, int u, int d) {
  int i, v;
  visited[u] = true;
  dist[p][u] = d;
  for (i = 0; i < A[u].size(); i++)
    if (!visited[A[u][i]]) dfs(p, A[u][i], d + W[u][i]);
}
int main() {
  int i, j, k, n;
  edge e;
  scanf("%d", &n);
  for (i = 1; i <= n; i++)
    for (j = 1; j <= n; j++) {
      scanf("%d", &matrix[i][j]);
      if (i != j) {
        e.u = i;
        e.v = j;
        e.cost = matrix[i][j];
        E.push_back(e);
      }
    }
  sort((E).begin(), (E).end());
  for (i = 1; i <= n; i++) parent[i] = i;
  for (i = 0; i < E.size(); i++) {
    if (_unite(E[i].u, E[i].v)) {
      A[E[i].u].push_back(E[i].v);
      A[E[i].v].push_back(E[i].u);
      W[E[i].u].push_back(E[i].cost);
      W[E[i].v].push_back(E[i].cost);
    }
  }
  for (i = 1; i <= n; i++) {
    _visit();
    dfs(i, i, 0);
  }
  for (i = 1; i <= n; i++)
    for (j = 1; j <= n; j++)
      if (matrix[i][j] != dist[i][j] || (matrix[i][j] == 0 && i != j)) {
        printf("%s\n", "NO");
        return 0;
      };
  printf("YES\n");
  return 0;
}
