线段树建图

对于一个图,n个节点,有向边,求点s到其他所有点的最短路。

题目给的边的方式:

u -> v

[l,r] -> v

v -> [l,r]

这样的话边数是O(n^2)级别的,怎么做?

假设把[1,n]建成segment tree 后,有tot个节点。

则建一个新图,新图有2 * tot + n个节点

新图多了2 * tot个节点,表示2棵线段树A,B

点的编号分类:

A - [1,tot]

B - [tot + 1,2 * tot]

C - [2 * tot + 1,2 * tot + n]

tree内节点:

A - 表示第1个线段树的点,由父节点向子节点连边,权为0

B - 表示第2个线段树的点,由子节点向父节点连边,权为0

叶节点:

A - 点x向原图对应的点连边,权为0,即x -> 2 * tot + x

B - 原图对应的点向点x连边,权为0,即2 * tot + x -> x + tot

在转换原图的边的时候:

u -> v   在C对应的节点连

v -> [l,r] C连向A中[l,r]对应节点

[l,r] -> v B中[l,r]对应节点连向C

时间: 2024-10-14 18:59:13

线段树建图的相关文章

POJ 1436 Horizontally Visible Segments(线段树建图+枚举)

题目连接:http://poj.org/problem?id=1436 题意:给一些线段,每个线段有三个值y1, y2, x代表起点为(x, y1),终点为(x, y2)的线段.当从一个线段可以作水平线到另一个线段并且不穿过其他线段时,就称这两个线段时水平可见的.当三个线段可以两两水平可见,就称为形成一个线段三角.问:在这些线段中有多少个这样的线段三角? 分析:可以把每条线段看做是一个点,如果它和其他线段是水平可见的,就将这两个点相连,由于是无向图,就是你能看到我,我也能看到你,所以需要连接两次

HDU5669 Road 分层最短路+线段树建图

分析:(官方题解) 首先考虑暴力,显然可以直接每次O(n^2) ?的连边,最后跑一次分层图最短路就行了. 然后我们考虑优化一下这个连边的过程 ,因为都是区间上的操作,所以能够很明显的想到利用线段树来维护整个图, 连边时候找到对应区间,把线段树的节点之间连边.这样可以大大缩减边的规模,然后再跑分层图最短路就可以了. 但是这样建图,每一次加边都要在O(logn)个线段树节点上加边,虽然跑的非常快,但是复杂度仍然是不科学的. 为了解决边的规模的问题,开两棵线段树,连边时候可以新建一个中间节点,在对应区

[线段树建图 bfs] BZOJ 3073 [Pa2011]Journeys

CA爷的题解:http://blog.csdn.net/CreationAugust/article/details/50739132 #include<cstdio> #include<cstdlib> #include<algorithm> #include<set> using namespace std; inline char nc() { static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) {

CF-787D-线段树建图+最短路

http://codeforces.com/problemset/problem/787/D 题目大意是给出一个有向图,有N个节点,初始节点在S,询问S到所有点最短路.边的读入方式有三种, 1 u v w  表示 u->v有一条边权为w的边, 2 v l r w ,表示v->[l,r]内的任意一个点支付w即可, 3 v l r w 表示从[l,r]内任意一个点到v支付w即可.直接构图的话可能会出现完全图,被卡死. 一种巧妙的构图方式是,由这些个区间联想到线段树(然而我并没有想到),我们不妨对2

BZOJ 1018 线段树维护图的连通性问题

思路: 我们可以搞一棵线段树 对于一段区间有6种情况需要讨论 左上右下.左上右上.左下右下.左下右上 这四种比较好维护 用左上右下举个例子吧 就是左儿子的左上右下&左区间到右区间下面有路&右儿子的左下右下 或者是左儿子的左上右上&左区间到右区间上面有路&右儿子的左上右下 还有两种  区间的左(右)端点上下能不能联通 需要维护 这种就是左儿子的上下连通或(左上右上&左上右下&左到右两条路都联通&右儿子的上下联通) (假设c1<c2) 最后要查的是

BZOJ 1018 线段树维护图连通性

用8个bool维护即可分别为LURU,LURD,LDRU,LDRD,LULD,RURD,Side[1],Side[2]即可. Side表示这一块有没有接到右边.Merge一下就可以了.码农题,WA了一次,发现未初始化,就AC了.. 1 #include <cstdio> 2 inline int Min(int x,int y) {return x>y?y:x;} 3 inline void Swap(int &x,int &y) {int t=x;x=y;y=t;} 4

[CF787D]遗产(Legacy)-线段树-优化Dijkstra(内含数据生成器)

Problem 遗产 题目大意 给出一个带权有向图,有三种操作: 1.u->v添加一条权值为w的边 2.区间[l,r]->v添加权值为w的边 3.v->区间[l,r]添加权值为w的边 求st点到每个点的最短路 Solution 首先我们思考到,若是每次对于l,r区间内的每一个点都执行一次加边操作,不仅耗时还耗空间. 那么我们要想到一个办法去优化它.一看到lr区间,我们就会想到线段树对吧. 没错啦这题就是用线段树去优化它. 首先我们建一棵线段树,然后很容易想到,我们只需要把这一棵线段树当做

java,线段树

线段树: 你可以理解成:线段组成的树,很多人问我,线段树到底有何用处,其实这个问题,你可以自己去刷题,然后总结出检验. 线段的具体理解,我看到一篇很好的博客,我就不展开了.博客地址:https://blog.csdn.net/iwts_24/article/details/81484561 基础题目: hdu1166敌兵布阵: 如果我们没有学过线段树,我们肯定是用模拟+暴力的方法. 模拟+暴力的方法代码: package Combat.com; import java.math.BigInteg

数据结构优化建图总结

数据结构优化建图总结 线段树优化建图 把要连的区间拆成log个点(线段树上的点)连要要连的点上,如果是区间连区间可以建\(\log^2\) 条边 注意,区间连进去和连出来的边顺序不一样,线段树建法也不同 单点连区间(连进去) 由于本质是链接所有根节点,线段树父亲向儿子连零边,保证能到达 区间连单点(连出去)由于所有根节点连这个点,线段树儿子向父亲连零边,能够连出去 此时就需要两颗线段树 例题:CF786B 我会告诉你们用大根堆维护dijkstra还过了前四个点 改longlong看线段树看了半天