【题目链接】
Line Graph L(G) can be considered as an operator on an undirected graph G just like Complementary Graph and Dual Graph.
Rikka generalizes Line Graph to edge-weighted undirected graphs. For a graph G=(V,E) , L(G) is still an edge-weighted undirected graph which is constructed in the following way:
For example, in the following picture, the right graph is the line graph of the left one. Vertex 1,2,3,4 in L(G) correspond to edge (1,2),(1,4),(1,3),(3,4) in G. And if all edges in the left graph have weight 1, the edges in the right graph will have weight 2.
Now, Rikka has an edge-weighted undirected complete graph G with n vertices. And she constructs a graph G’=L(G). It is clear that G’ is connected.
Let d(i,j) be the length of the shortest path between vertex i,j in G’(the length of each edge is equal to its weight), K be the number of vertices in G’, Rikka wants you to calculate.
输入描述:
The first line contains a single number t(1 ≤ t ≤ 3), the number of the testcases.
For each testcase, the first line contains one single integer n(2 ≤ n ≤ 500).
Then n lines follow, each line contains n integers wi,j(0 ≤ wi,j ≤ 109), the weight of each edge in G. Since there are no self circles in G, the value of wi,i is meaningless.
The input guarantees that for all 1 ≤ i ≠ j ≤ n, wi,i=0 and wi,j = wj,i.
输出描述:
For each testcase, output a single line with a single number, the answer modulo 998244353.
示例1
输入
3
2
0 1
1 0
3
0 1 1
1 0 1
1 1 0
4
0 1 1 1
1 0 2 2
1 2 0 3
1 2 3 0
输出
0
6
56
给一个500个点的无向完全图,边有权值,将它的边变成点,点变成边之后求每对点的最短路之和,新图的点权即为对应的旧图的边,新图的边权为其所连的两个点的权值和。
解题思路
//点最短路:点和点之间的最短路
//边最短路:边和边之间的最短路
1、首先,新图是构不出来的,只能在旧图里算边和边的最短路。
2、边i和边j的最短路是它们各自权值加上中间的边的权值的两倍。
3、算最短路时,作为起止点的那两条边算的次数是一定的,都和其他所有边连一次,和哪一条路最短无关,可以单独算。
4、在3的基础上,用d[i][j]表示点i到点j的最短路,那对于两条边(a,b)和(c,d)的最短路,就再加两倍的min(d[a][c],d[a][d],d[b][c],d[b][d])。
5、新的问题转化成了求每个点最短路的贡献,即每个点最短路被用了多少次。
6、枚举n*(n-1)/2条边,对边(a,b)来说,到点i的最短路是min(d[a][i],d[b][i]),把这条边到其他点所有的最短路排序,第k短的恰好会被用(n-k)次,可以理解为先用短的,每次都和其他没有计算过的全部计算一遍。
步骤6 建议参考博客:牛客网暑期ACM多校训练营(第十场) F - Rikka with Line Graph 图论 弗洛伊德+思维
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define LL long long
const int maxn=507;
const LL INF=((LL)2<<31)-1;
const int mod = 998244353;
LL a[maxn][maxn],dis[maxn][maxn];
LL d[maxn];
void floyed(int n)
{
int i,j,k;
for(k=1;k<=n;k++)
{
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
}
}
}
int main()
{
LL n,m,i,j,k,x,y,len,k1,k2,v,loc,sum,ans;
int T;
scanf("%d",&T);
while(T--)
{
scanf("%lld",&n);
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
scanf("%lld",&a[i][j]);
dis[i][j]=a[i][j];
}
}
floyed(n);///最短路预处理
ans=0;
sum=n*(n-1)/2;
for(i=1;i<=n;i++)
{
for(j=i+1;j<=n;j++)
{
ans+=a[i][j]*(sum-1)%mod;///步骤三,加起止点只需要算一次的边
}
}
ans%=mod;
for(i=1;i<=n;i++)
{
for(j=i+1;j<=n;j++)
{
for(k=1;k<=n;k++)
{
d[k]=min(dis[i][k],dis[j][k]);///步骤六,更新到边的最短路排序
}
sort(d+1,d+1+n);
for(k=1;k<=n;k++)
{
ans+=(n-k)*d[k]%mod;
}
ans%=mod;
}
}
printf("%lld\n",ans);
}
return 0;
}