#include <bits/stdc++.h>
using namespace std;
const int maxn = 2500 + 100;
const int maxm = 4000000 + 100;
const int logmaxn = 20;
struct Edge {
  int u, v, w;
  Edge() {}
  Edge(int u, int v, int w) : u(u), v(v), w(w) {}
  bool operator<(const Edge& tmp) const { return w < tmp.w; }
} e[maxm];
int n;
int g[maxn][maxn];
int p[maxn], cnt;
vector<int> G[maxn], C[maxn];
int find(int x) { return x == p[x] ? x : p[x] = find(p[x]); }
struct LAC {
  int n;
  int fa[maxn], cost[maxn], L[maxn];
  int anc[maxn][logmaxn];
  int dis[maxn][logmaxn];
  void preprocess() {
    for (int i = 0; i < n; i++) {
      anc[i][0] = fa[i];
      dis[i][0] = cost[i];
      for (int j = 1; (1 << j) < n; j++) anc[i][j] = -1;
    }
    for (int j = 1; (1 << j) < n; j++)
      for (int i = 0; i < n; i++)
        if (anc[i][j - 1] != -1) {
          int a = anc[i][j - 1];
          anc[i][j] = anc[a][j - 1];
          dis[i][j] = dis[i][j - 1] + dis[a][j - 1];
        }
  }
  int query(int p, int q) {
    int log;
    int ans = 0;
    if (L[p] < L[q]) swap(p, q);
    for (log = 1; (1 << log) <= L[p]; log++)
      ;
    log--;
    for (int i = log; i >= 0; i--)
      if (L[p] - (1 << i) >= L[q]) {
        ans += dis[p][i];
        p = anc[p][i];
      }
    if (p == q) return ans;
    for (int i = log; i >= 0; i--)
      if (anc[p][i] != -1 && anc[p][i] != anc[q][i]) {
        ans += dis[p][i];
        p = anc[p][i];
        ans += dis[q][i];
        q = anc[q][i];
      }
    ans += cost[p];
    ans += cost[q];
    return ans;
  }
} Gintoki;
void dfs(int u, int fa, int depth) {
  Gintoki.L[u] = depth;
  for (int i = 0; i < G[u].size(); i++) {
    int v = G[u][i];
    if (v != fa) {
      Gintoki.fa[v] = u;
      Gintoki.cost[v] = C[u][i];
      dfs(v, u, depth + 1);
    }
  }
}
int main() {
  scanf("%d", &n);
  for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++) scanf("%d", &g[i][j]);
  for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++) {
      if (g[i][j] && i == j) {
        printf("NO\n");
        return 0;
      }
      if (!g[i][j] && i != j) {
        printf("NO\n");
        return 0;
      }
      if (g[i][j] != g[j][i]) {
        printf("NO\n");
        return 0;
      }
    }
  for (int i = 0; i < n; i++)
    for (int j = i + 1; j < n; j++)
      if (g[i][j]) e[cnt++] = Edge(i, j, g[i][j]);
  sort(e, e + cnt);
  for (int i = 0; i < n; i++) p[i] = i;
  for (int i = 0; i < cnt; i++) {
    int x = e[i].u, y = e[i].v, d = e[i].w, u = find(x), v = find(y);
    if (u != v) {
      p[u] = v;
      G[x].push_back(y), C[x].push_back(d);
      G[y].push_back(x), C[y].push_back(d);
    }
  }
  Gintoki.n = n;
  dfs(0, -1, 0);
  Gintoki.preprocess();
  for (int i = 0; i < n; i++)
    for (int j = i + 1; j < n; j++) {
      if (g[i][j] != Gintoki.query(i, j)) {
        printf("NO\n");
        return 0;
      }
    }
  printf("YES\n");
  return 0;
}
