题目链接:https://www.nowcoder.com/acm/contest/148/F
越来越懒的写题意和思路了。。。
(just截图
放上截图也是为了以后不用搜。。
那再写一些自己的思路:
先跑出每两个点之间的最短路o(n^3),枚举两个点,再把其他点到该两点的最短路取min放到vector里,排序,对于每个点作为经过路径做出的贡献是比他大的点的个数(好吧我也不知道在写一些什么。。
本来是要乘2的但这里不乘是因为重复计算了
代码送上:(跑了9458ms大概是写挂了吧哈哈
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
typedef long long ll;
ll mp[505][505],dis[505][505];
const int mod=998244353;
vector<ll>v;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d", &n);
ll ans=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%lld",&mp[i][j]);
dis[i][j]=mp[i][j];
}
}
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
ans=(ans+mp[i][j])%mod;
ans=ans*(n*(n-1)/2-1)%mod;
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
v.clear();
for(int k=1;k<=n;k++)
{
v.push_back(min(dis[i][k],dis[j][k]));
}
sort(v.begin(),v.end());
for(int k=0;k<v.size()-1;k++)
{
ans=(ans+v[k]*(v.size()-k-1)%mod)%mod;
}
}
}
printf("%lld\n", ans);
}
return 0;
}