CSP认证201609-4交通规划[C++题解]:最短路径树、dijkstra求单源最短路、递推思想
题目分析
来源:acwing
分析: 这题是最短路树。保持原图中所有点到根结点的最短距离不变,然后在原图中选择一些边,使所有点连通的最短路是多长。
最短路径树,是一种使用最短路径算法生成的数据结构树。
定义
考虑一个连通无向图G,一个以顶点v为根节点的最短路径树T是图G满足下列条件的生成树——树T中从根节点v到其它顶点u的路径距离,在图G中是从v到u的最短路径距离。
来源:维基百科
在这个生成树上的两点a和b,如果a能通过b点到达根结点,那么有一个等式d[b]=d[a]+wa−>bd[b] = d[a] + w_{a->b}d[b]=d[a]+wa−>b,其中d[b]d[b]d[b]和d[a]d[a]d[a]表示该点到根的距离,wa−>bw_{a->b}wa−>b表示a到b的距离。
既然有了这个等式,其实每个点到根结点的路径的选项就有限了,因为该点到根的最小距离可以求出来,该点通过其他点到根结点一定满足上面的等式,所以我们可以预处理出来可行的通路!做法是dijkstra求每个点的最短路,然后遍历除根之外的所有点,看看它们的邻边有哪些是满足上面这个等式的。
其实,上面等式还说明了另一个问题,就是d[a] 一定比d[b]小,因为边权都是正的,这就启发我们将单源最短路的点从小到大排序,从小到大开始查看是否满足这个等式,满足的可以和根结点形成树!
我们假设f(i)表示把前i个点合法挂到根结点所需要的总代价。
在挂第i个点的时候,只有几个点满足上述等式(我们称之为备选边),
所以有 f(i)=min[f(i−1)+w(被选点→i)]f(i) = min[f(i-1) + w(被选点\rightarrow i)]f(i)=min[f(i−1)+w(被选点→i)]
到这一步,这里公共的是f(i-1),我们只需要求出最小的w(某点->i点)即可。
所以,我们最后求的答案就是不断从根的邻点遍历,求出每个点权值最小的边(该点需要满足d[b]=d[a]+wa−>bd[b] = d[a] + w_{a->b}d[b]=d[a]+wa−>b这个等式)
所以,核心代码如下
for(int a = 2; a <= n; a ++){int minw = INF; // 遍历所有的邻点for(int j = h[a]; ~j; j = ne[j]){int b= e[j];if(dist[a] == dist[b] + w[j])minw = min(minw, w[j]);}res += minw; // 每个点找到权值最小的边}AC代码
题目链接
总结
以上是生活随笔为你收集整理的CSP认证201609-4交通规划[C++题解]:最短路径树、dijkstra求单源最短路、递推思想的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: CSP认证201609-2火车购票[C+
- 下一篇: CSP认证201612-1中间数[C++