Powered by:NEFU AB-IN
Link
文章目录
- 3512. 最短距离总和
- 题意
- 思路
- 代码
3512. 最短距离总和
-
题意
给定一张带权无向完全图,设点的编号为 1,2,3,4,5…n(以邻接矩阵的形式给出)。
计算依次拿走第 i个点后,剩余所有点到其他点的最短距离之和的总和(具体请看样例)。 -
思路
floyd 本身也是dp,状态表示与状态计算如下图
- 三重状态可压缩至两层
- 题目是
- 一开始所有点都在,从小往大拿点i
- 等价于
- 一开始所有点都不在,从大往小放进去点i
- 所以我们就可以用倒着的floyd算法(普通的floyd的k是从1开始遍历,也就是将1开始扩进去),先将n扩进S(S集合代表扩充的中间点),所以
d[i][j]
就表示i走到j,中间点只经过S集合,的最短距离 - 由于中间点已经在S集合中,只需保证起点和终点也在S中,整个路径的点就在S中,由于我们是从大往小加的,只要起点和终点大于等于k即可,说明他们俩在S中,所以此时就先进行dp操作,再让答案加上
d[i][j]
即可
注:
- 每次
if i >= k and j >= k
时,都得加上,因为每当最外层的k挑选一个值时,再进行i和j的二重循环,每次k进来时,i和j只有一次碰面机会算最短距离 - k不能取1,因为如果取1就代表全拿走了,不符合题目要求
-
代码
''' Author: NEFU AB-IN Date: 2023-05-20 20:32:18 FilePath: \Acwing\3512\3512.py LastEditTime: 2023-05-20 21:50:19 ''' # import import sys, math from collections import Counter, deque from heapq import heapify, heappop, heappush, nlargest, nsmallest from bisect import bisect_left, bisect_right from datetime import datetime, timedelta from string import ascii_lowercase, ascii_uppercase class sa: def __init__(self, x, y): self.x = x self.y = y def __lt__(self, x): pass # Final N = int(1e3 + 10) INF = int(2e9) # Define sys.setrecursionlimit(INF) input = lambda: sys.stdin.readline().rstrip("\r\n") # Remove when Mutiple data read = lambda: map(int, input().split()) letterTonumber = lambda x: ord(x.upper()) - 64 # —————————————————————Division line —————————————————————— res = 0 dis = [[0] * N for _ in range(N)] n, = read() for i in range(1, n + 1): dis[i][1:] = read() for k in range(n, 1, -1): # 若k=1 代表把k为1的点也算进去了 for i in range(1, n + 1): for j in range(1, n + 1): dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]) if i >= k and j >= k: res += dis[i][j] print(res)