这场比赛对我来说最有价值就是这题。。读完题肯定会有一个朴素的想法,枚举不能使用的k跑
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 305;
int g[20][maxn][maxn];
ll ans = 0;
int n;
void floyd(int l,int r,int dep){
if(l==r){
return;
}
if(l+1 == r){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==l || j==l){
continue;
}
ans += g[dep][i][j];
}
}
return;
}
int mid = (l+r)>>1;
//relex mid+1 r
memcpy(g[dep+1],g[dep],sizeof(g[dep]));
for(int k=mid;k<r;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(g[dep+1][i][k] == -1 || g[dep+1][k][j]==-1){
continue;
}
if(g[dep+1][i][j] == -1){
g[dep+1][i][j] = g[dep+1][i][k]+g[dep+1][k][j];
}
g[dep+1][i][j] = min(g[dep+1][i][j],g[dep+1][i][k]+g[dep+1][k][j]);
}
}
}
floyd(l,mid,dep+1);
//relex l mid-1
memcpy(g[dep+1],g[dep],sizeof(g[dep]));
for(int k=l;k<=mid-1;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(g[dep+1][i][k] == -1 || g[dep+1][k][j]==-1){
continue;
}
if(g[dep+1][i][j] == -1){
g[dep+1][i][j] = g[dep+1][i][k]+g[dep+1][k][j];
}
g[dep+1][i][j] = min(g[dep+1][i][j],g[dep+1][i][k]+g[dep+1][k][j]);
}
}
}
floyd(mid,r,dep+1);
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%d",&g[0][i][j]);
}
}
floyd(1,n+1,0);
cout<<ans<<endl;
return 0;
}