#include <bits/stdc++.h>
using namespace std;
long long n, V;
vector<vector<long long>> dist;
long long minKey(long long key[], bool mstSet[]) {
  long long min = 1e18, min_index;
  for (long long v = 0; v < V; v++)
    if (mstSet[v] == false && key[v] < min) min = key[v], min_index = v;
  return min_index;
}
struct obj {
  long long v;
  long long w;
};
void dfs(long long d, long long s, vector<vector<obj>>& tdist, long long x,
         vector<long long>& vis) {
  vis[s] = true;
  for (long long i = 0; i < tdist[s].size(); ++i) {
    if (!vis[tdist[s][i].v]) {
      if ((d + tdist[s][i].w) != dist[x][tdist[s][i].v]) {
        cout << "NO";
        exit(0);
      }
      dfs(d + tdist[s][i].w, tdist[s][i].v, tdist, x, vis);
    }
  }
}
long long prllMST(long long parent[], long long n,
                  vector<vector<long long>> graph) {
  vector<vector<obj>> tdist(n);
  for (long long i = 1; i < n; ++i) {
    tdist[parent[i]].push_back({i, graph[parent[i]][i]});
    tdist[i].push_back({parent[i], graph[parent[i]][i]});
  }
  for (long long i = 0; i < n; ++i) {
    vector<long long> vis(n, 0);
    dfs(0, i, tdist, i, vis);
  }
  cout << "YES";
  exit(0);
}
void primMST(vector<vector<long long>> graph) {
  long long parent[V];
  long long key[V];
  bool mstSet[V];
  for (long long i = 0; i < V; i++) key[i] = 1e18, mstSet[i] = false;
  key[0] = 0;
  parent[0] = -1;
  for (long long count = 0; count < V - 1; count++) {
    long long u = minKey(key, mstSet);
    mstSet[u] = true;
    for (long long v = 0; v < V; v++)
      if (graph[u][v] && mstSet[v] == false && graph[u][v] < key[v])
        parent[v] = u, key[v] = graph[u][v];
  }
  prllMST(parent, V, graph);
}
int main() {
  ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  cin >> n;
  V = n;
  vector<long long> a(n);
  dist.resize(n, a);
  for (long long i = 0; i < n; ++i) {
    for (long long j = 0; j < n; ++j) {
      cin >> dist[i][j];
      if (i == j) {
        if (!dist[i][j])
          continue;
        else {
          cout << "NO";
          exit(0);
        }
      } else {
        if (dist[i][j])
          continue;
        else {
          cout << "NO";
          exit(0);
        }
      }
    }
  }
  for (long long i = 0; i < n; ++i) {
    for (long long j = 0; j < n; ++j) {
      if (dist[i][j] != dist[j][i]) {
        cout << "NO";
        return 0;
      }
    }
  }
  primMST(dist);
  return 0;
}
