题目链接:点我点我
题意:给出一个最短路的图,询问是否正确,如果正确的话,输出遍历所有点的最短路径和。
题解:判断是否正确的,直接再一次Floyd,判断是否会有A[i][k]+A[k][j]<A[i][j](通过中间点k使得两点间距离更短),如果有的话,直接输出-1。
要遍历到所有道路,并且路径和最小,我们可以尽可能用用中间点的路径(A[i][k]+A[k][j]==A[i][j]),这样本来遍历两个点,就可以遍历3个点了,
最后加的时候记得不要从重复加,从最小点往后加,不要再往前加,不然就重复了。
(其实如果重复计算也不要紧,就相当于过去又回来,会是答案的两倍,除以2就行了)
1 #include <iostream> 2 #include <algorithm> 3 using namespace std; 4 5 const int N=333; 6 typedef long long LL; 7 int A[N][N],idx[N][N]; 8 9 int main(){ 10 int n,flag=1; 11 LL ans=0; 12 cin>>n; 13 for(int i=1;i<=n;i++) 14 for(int j=1;j<=n;j++) 15 cin>>A[i][j],idx[i][j]=0; 16 17 for(int k=1;k<=n;k++){ 18 for(int i=1;i<=n;i++){ 19 for(int j=1;j<=n;j++){ 20 if(i==j||i==k||j==k) continue; 21 if(A[i][k]+A[k][j]<A[i][j]) flag=0; 22 if(A[i][k]+A[k][j]==A[i][j]) idx[i][j]=1; 23 } 24 } 25 } 26 27 if(!flag) {cout<<-1<<endl;return 0;} 28 for(int i=1;i<=n;i++){ 29 for(int j=i+1;j<=n;j++){//这边可以直接从1开始,这样的话相当于重复计算一次,最后ans/2就行了 30 if(!idx[i][j]) ans+=A[i][j]; 31 } 32 } 33 34 cout<<ans<<endl; 35 return 0; 36 }
时间: 2024-11-03 05:42:33