#include <bits/stdc++.h>
using namespace std;
int Maps[2007][2007];
int Fa[2007], N;
int dis[2007][2007];
struct Node {
  int L, R, W;
  bool operator<(Node a) const { return W < a.W; }
} edge[2007 * 2007];
struct Lists {
  int v, w;
};
vector<Lists> G[2007];
int Finds(int x) {
  if (x != Fa[x]) Fa[x] = Finds(Fa[x]);
  return Fa[x];
}
void dfs(int u, int fa, int begins) {
  Lists temp;
  for (int i = 0; i < G[u].size(); i++) {
    temp = G[u][i];
    int v = temp.v;
    if (v == fa) continue;
    dis[begins][v] = dis[begins][u] + temp.w;
    dfs(v, u, begins);
  }
}
int main() {
  while (~scanf("%d", &N)) {
    for (int i = 1; i <= N; i++)
      for (int j = 1; j <= N; j++) scanf("%d", &Maps[i][j]);
    int flag = 1;
    for (int i = 1; i <= N; i++) {
      Fa[i] = i;
      for (int j = 1; j <= N; j++) {
        if ((j == i && Maps[i][j]) || (i != j && Maps[i][j] == 0) ||
            (Maps[i][j] != Maps[j][i])) {
          flag = 0;
          break;
        }
      }
      if (!flag) break;
    }
    if (!flag)
      printf("NO\n");
    else {
      int cnt = 0;
      Lists temp1, temp2;
      for (int i = 1; i <= N; i++)
        for (int j = i + 1; j <= N; j++)
          edge[cnt].L = i, edge[cnt].R = j, edge[cnt++].W = Maps[i][j];
      sort(edge, edge + cnt);
      for (int i = 0; i < cnt; i++) {
        int u = edge[i].L, v = edge[i].R, w = edge[i].W;
        int fx = Finds(u), fy = Finds(v);
        if (fx != fy) {
          temp1.v = v, temp1.w = w;
          temp2.v = u, temp2.w = w;
          G[u].push_back(temp1);
          G[v].push_back(temp2);
          Fa[fx] = fy;
        }
      }
      int flag1 = 1;
      for (int i = 1; i <= N; i++) {
        dis[i][i] = 0;
        dfs(i, 0, i);
        for (int j = 1; j <= N; j++) {
          if (Maps[i][j] != dis[i][j]) {
            flag1 = 0;
            break;
          }
        }
        if (!flag1) break;
      }
      if (!flag1)
        printf("NO\n");
      else
        printf("YES\n");
    }
  }
  return 0;
}
