floyd变形 每次破坏一条边 问破坏这条边后所有国家距离之和
如果按照题目所给顺序求解 感觉每次都要跑一遍floyd n^4肯定TLE
但是逆序考虑 每次增边 然后松弛就好办了
floyd板子就是挑当前一个点 k 看其他两点 i j 能否通过 k 来进行松弛 这里就是把点换成边而已
#include <bits/stdc++.h>
using namespace std;
#define N 0x3f3f3f3f3f3f3f3f
#define ll long long
ll e[210][210];
ll ans[210];
int u[210],v[210],w[210];
int n,q;
void floyd();
void calculate();
int main()
{
int i,j;
while(scanf("%d",&n)!=EOF)
{
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
scanf("%lld",&e[i][j]);
}
}
scanf("%d",&q);
for(i=1;i<=q;i++)
{
scanf("%d%d",&u[i],&v[i]);
w[i]=e[u[i]][v[i]];
e[u[i]][v[i]]=N;
}
floyd();
calculate();
for(i=1;i<=q;i++)
{
if(ans[i]!=N) printf("%lld\n",ans[i]);
else printf("INF\n");
}
}
return 0;
}
void floyd()
{
ll sum;
int i,j,k,flag;
for(k=1;k<=n;k++)
{
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(e[i][j]>e[i][k]+e[k][j])
{
e[i][j]=e[i][k]+e[k][j];
}
}
}
}
sum=0,flag=0;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(e[i][j]==N)
{
flag=1;
break;
}
sum+=e[i][j];
}
if(flag==1) break;
}
if(flag==1) ans[q]=N;
else ans[q]=sum;
return;
}
void calculate()
{
ll sum;
int k,i,j,flag;
for(k=q;k>=2;k--)
{
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(e[i][j]>e[i][u[k]]+w[k]+e[v[k]][j])
{
e[i][j]=e[i][u[k]]+w[k]+e[v[k]][j];
}
}
}
sum=0,flag=0;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(e[i][j]==N)
{
flag=1;
break;
}
sum+=e[i][j];
}
if(flag==1) break;
}
if(flag==1) ans[k-1]=N;
else ans[k-1]=sum;
}
return;
}