题目链接
题意
一共有N个城市,通过N-1条边连接。
现在给出一个N x N的矩阵,表示从i->j的最短路径,求能否根据这个N x N的矩阵求出最短路,如果最短路出错,输出-1
解决
k
/\
/ \
i /____\ j
- 因为N只有300级别,所以可以n^3算法
- 设三个点 i , j ,k
- 如果存在i->k + k->j的最短路径和< i->j的最短距离,那么这个矩阵是错误的。
- 如果存在i->k + k->j的最短路径和= i->j的最短距离,那么i->j的这条边是不需要存在的(走同样的路程,能通过更多的点(k点),所以选择i->k->j而不是i->j)
#include<bits/stdc++.h>
using namespace std;
int maps[305][305];
bool flag[305][305];
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%d",&maps[i][j]);
}
}
bool ok = true;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
for(int k=1;k<=n;k++){
if(i==j) continue;
if(i==k) continue;
if(j==k) continue;
if(maps[i][k]+maps[k][j] < maps[i][j]) ok = false; //存在比“最短路”更短的路,错误
if(maps[i][k]+maps[k][j] == maps[i][j]) flag[i][j] = flag[j][i] = 1;
//从i到j的边是不需要存在的
}
}
}
if(!ok){
puts("-1");
return 0;
}
long long ans = 0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j) continue;
if(flag[i][j]) continue; //不需要存在的路
ans += maps[i][j];
}
}
printf("%lld\n",ans/2); //i->j j->i算了两遍
return 0;
}