题意
题解
容易想到
floyed
干的就是类似的事情。
但是我们算点
i
<script type="math/tex" id="MathJax-Element-2">i</script> 的答案时,其他点都要插入。
我们分治搞就行了,分治到单一节点时进行答案查询。
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=305;
int n,a[N][N];
LL ans;
void Solve(int L,int R,int dis[N][N]){
if(L==R){
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i!=j&&i!=L&&j!=L) ans+=dis[i][j]>=1e+9?-1:dis[i][j];
return;
}
int mid=(L+R)>>1, tmp[N][N];
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) tmp[i][j]=dis[i][j];
for(int k=mid+1;k<=R;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
tmp[i][j]=min(tmp[i][j],tmp[i][k]+tmp[k][j]);
Solve(L,mid,tmp);
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) tmp[i][j]=dis[i][j];
for(int k=L;k<=mid;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
tmp[i][j]=min(tmp[i][j],tmp[i][k]+tmp[k][j]);
Solve(mid+1,R,tmp);
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
scanf("%d",&a[i][j]); if(a[i][j]==-1) a[i][j]=1e+9;
}
Solve(1,n,a);
printf("%lld\n",ans);
}