codeforces 786B (线段树构图+最短路径)

版权声明:本文为博主原创文章,未经博主允许不得转载。 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。

1n,q105

解答

用线段树划分区间,那么和[l,r]相关的区间不超过 2log2n 个。

若一个线段树区间[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需要连 (log2n)2 条边,边数多最短路的时间复杂度就大)。

总点数V不超过 4n+q

总边数E不超过 4n+4qlog2n

用dijkstra堆优化的时间复杂度是 O(V+Elog2E)

通过代码

相同类型题目

hdu5669 通过代码

猜你喜欢

转载自blog.csdn.net/wuxufanzhong/article/details/73791981