版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wuxufanzhong/article/details/73791981
codeforces 786B (线段树构图+最短路径)
图论
构图
最短路径
codeforces
题目大意
有n个地点,编号为1到n,一开始互不相连。q次连边,每次连边有三种方式。
- 从v到u连一条花费是w的边
- 从v到编号为[l,r]的所有点都连一条花费是w的边
- 从编号为[l,r]的所有点到v都连一条花费是w的边
连完q次边之后,问从s出发,到达所有点的最短路径,不能到达则输出-1。
解答
用线段树划分区间,那么和[l,r]相关的区间不超过
若一个线段树区间[le,ri]对应的下标是w,定义id1[w]表示[le,ri]中任意一个点,id2[w]表示[le,ri]中的全部点。那么初始构图如下:
- 如果该区间是叶子(le==ri),那么id1[w]=id2[w]。
- 如果该区间非叶子(le< ri),把该区间拆成两个点id1[w]和id2[w]。设lw是w的左区间,rw是w的右区间,id1[lw]和id1[rw]均向id1[w]连一条花费是0的边;id2[w]分别向id2[lw]和id2[rw]连一条花费是0的边。
上述连边的理由是:
- id1[w]表示其中一个点的最短路,其最短路等于左右孩子的最短路。
- id2[w]表示全部点的最短路,其最短路可以更新左右孩子的最短路。
- 根据定义id2[w]可以向id1[w]连一条花费为0的边,但是没必要。
可以把连边看成两棵线段树,其中一棵从下往上连边,另外一棵从上往下连边,叶子结点将两棵树连在一起。
然后q次询问,每个询问设一个点,记为change。假设区间从[x1,y1]到[x2,y2]连边,把[x1,y1]的区间的Id1编号连向change,change连向[x2,y2]的区间的id2编号(花费其中一条是0,另一条是w)。(本题可以省去change,但如果要做区间向区间连边的话,没有change需要连
总点数V不超过
总边数E不超过
用dijkstra堆优化的时间复杂度是