題目鏈接
題意
一共有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;
}