#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

#define REP(i,n) for(ll i=0;i<n;++i)
#define SORT(name) sort(name.begin(), name.end())
#define ZERO(p) memset(p, 0, sizeof(p))
#define MINUS(p) memset(p, -1, sizeof(p))

#define MOD 1000000007
#define INF 1000000000000
#define MAX_N 310
#define MAX_V MAX_N

ll N;
ll A[MAX_N][MAX_N];
ll clear[MAX_N][MAX_N];
vector< pair< ll, pair<ll, ll> > > load; // 距離, from, to

struct edge{ ll to, cost; };
typedef pair<ll, ll> P;   // first は最短距離、 second は頂点の番号
ll V;
vector<edge> G[MAX_V];      // ノード i からのびている edge の vector 。ダイクストラ前に自分で入力する

ll d[MAX_V];
//ll prev_p[MAX_V];  // 経路も求める場合は必要
// 始点 s から各頂点への最短距離を求める
ll dijkstra(ll s) {
    // greater<P>を指定することでfirstが小さい順に取り出せるようにする
    priority_queue<P, vector<P>, greater<P> > que;
    fill(d, d + V, INF);
    //fill(prev_p, prev_p + V, -1); // 経路を求めるなら有効
    d[s] = 0;
    que.push(P(0, s));
    while(!que.empty()) {
        P p = que.top(); que.pop();
        ll v = p.second;
        if(d[v] < p.first){ continue; }
        REP(i, G[v].size()) {
            edge e = G[v][i];
            if(d[e.to] > d[v] + e.cost) {
                d[e.to] = d[v] + e.cost;
                //prev_p[e.to] = v;   // 経路も求めるなら有効
                que.push(P(d[e.to], e.to));
            }
        }
    }
    return 0;
}

int main()
{
    ZERO(clear);
    cin >> N;
    V = N;
    REP(i, N) {
        REP(j, N) {
            scanf("%lld", &A[i][j]);
            // とりあえず全部 INF でつなぐ
            if(i != j) {
                pair<ll, pair<ll, ll> > tmp_p =
                    make_pair(A[i][j], make_pair(i, j));
                load.push_back(tmp_p);
                //edge tmp;
                //tmp.to = j;
                //tmp.cost = INF;
                //G[i].push_back(tmp);
            }
        }
    }
    // 簡易チェック
    REP(i, N) {
        REP(j, N) {
            if(A[i][j] != A[i][j]) {
                printf("-1\n");
                return 0;
            }
        }
    }
    SORT(load);
    ll ans = 0;
    for(pair< ll, pair<ll, ll>> l_tmp : load) {
        ll dist = l_tmp.first;
        ll from = l_tmp.second.first;
        ll to = l_tmp.second.second;
        if(clear[from][to] != 0) {
            //ans += dist;
            continue;
        }
        //printf("from: %lld to: %lld d[to]: %lld dist: %lld\n",
        //        from, to, d[to], dist);
        dijkstra(from);
        if(d[to] > dist) {
            edge tmp;
            tmp.to = to;
            tmp.cost = dist;
            G[from].push_back(tmp);
            tmp.to = from;
            G[to].push_back(tmp);
            // G の更新
            //for(auto it = G[from].begin(); it != G[from].end(); ++it) {
            //    if(it->to == to) {
            //        it->cost = dist;
            //        break;
            //    }
            //}
            //for(auto it = G[to].begin(); it != G[to].end(); ++it) {
            //    if(it->to == from) {
            //        it->cost = dist;
            //        break;
            //    }
            //}
            ans += dist;
        }
        else if(d[to] < dist) {
            printf("-1\n");
            return 0;
        }
        clear[from][to] = 1;
        clear[to][from] = 1;
    }
    printf("%lld\n", ans);

    return 0;
}


Measured memory_bytes: 6132