// https://atcoder.jp/contests/abc074/tasks/arc083_b
// <Floyed>
// 1. 跑一边floyed检查是否有边被更新, 从而判断是否A中所有都为最短路
// 2. 在Floyed过程中, 记录被更新的边 a[i][j], 这些边是传递产生的边, 没有必要
// (想到了离散数学中的传递性, 偏序集的哈斯图 ??)
// 注意: 不能直接碰到传递边就 -a[i][j], 因为可能重复, 因而需要先标记, 后计算
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
using LL = long long;
const int N = 310;
int a[N][N]; // A
int b[N][N]; // backup
bool st[N][N];
void solv()
{
int n;
cin >> n;
LL ans = 0;
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= n; j ++)
{
cin >> a[i][j];
b[i][j] = a[i][j];
ans += a[i][j];
}
for (int k = 1; k <= n; k ++)
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= n; j ++)
{
if (a[i][j] == a[i][k] + a[k][j] && i != k && j != k)
{
// ans -= a[i][j]; // 不能直接计算, 要先标记(避免重复计算)
st[i][j] = true;
// cout << "ij = " << i << " " << j << endl;
}
a[i][j] = min(a[i][k] + a[k][j], a[i][j]);
}
if (memcmp(a, b, sizeof a))
{
cout << -1 << endl;
return;
}
else
{
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= n; j ++)
if (st[i][j]) ans -= a[i][j];
cout << ans / 2 << endl;
}
}
int main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int T = 1;
// cin >> T;
while (T --)
{
solv();
}
return 0;
}
标签:abc074d,int,LL,long,ans,include
From: https://www.cnblogs.com/o2iginal/p/17542991.html