HDU5669 Road 分层最短路+线段树建图
分析:(官方题解)
首先考虑暴力,显然可以直接每次O(n^2)
的连边,最后跑一次分层图最短路就行了.
然后我们考虑优化一下这个连边的过程 ,因为都是区间上的操作,所以能够很明显的想到利用线段树来维护整个图,
连边时候找到对应区间,把线段树的节点之间连边.这样可以大大缩减边的规模,然后再跑分层图最短路就可以了.
但是这样建图,每一次加边都要在O(logn)个线段树节点上加边,虽然跑的非常快,但是复杂度仍然是不科学的.
为了解决边的规模的问题,开两棵线段树,连边时候可以新建一个中间节点,在对应区间的节点和中间节点之间连边
进一步缩减了边的规模,强行下降一个数量级
最后跑一下分层图最短路就行了
复杂度O(mlog^2n)
什么你会线段树但是不会分层图最短路?安利JLOI2011飞行路线.
因为边的数目还是相对比较多的,所以不能使用SPFA,而要使用Heap-Dijkstra来做最短路,
但是不排除某些厉害的选手有特殊的SPFA姿势可以做或者普通 SPFA写的比较优美就不小心跑过去了...
注:出题人的题解写的很详细了,然后JLOI2011飞行路线是BZOJ2763 直接去做就好了
然后我的建图刚开始不太完善,跑了600+ms,然后后来完善了一下,按线段树节点建图(这就是题解)
不过每个线段树的节点不需要和它的区域内所有的点连边,只需要按照线段树的结构,连它的左右儿子就行了
代码:
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <string.h>
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
const int N=5e4+;
int d[][N*+],head[N*+],tot,n,m,k;
struct Edge{
int v,w,next;
};
vector<Edge>edge;
void add(int u,int v,int w){
edge.push_back(Edge{v,w,head[u]});
head[u]=edge.size()-;
}
struct Node{
int cur,v,dis;
bool operator<(const Node &rhs)const{
return dis>rhs.dis;
}
};
priority_queue<Node>q;
bool vis[][N*+];
int dij(){
memset(d,INF,sizeof(d));
memset(vis,,sizeof(vis));
d[][*N+]=;
q.push(Node{,*N+,});
while(!q.empty()){
int cur=q.top().cur,u=q.top().v;
q.pop();
if(vis[cur][u])continue;
vis[cur][u]=;
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].v;
if(!vis[cur][v]&&d[cur][v]>d[cur][u]+edge[i].w){
d[cur][v]=d[cur][u]+edge[i].w;
q.push(Node{cur,v,d[cur][v]});
}
if(cur+>k)continue;
if(!vis[cur+][v]&&d[cur+][v]>d[cur][u]){
d[cur+][v]=d[cur][u];
q.push(Node{cur+,v,d[cur+][v]});
}
}
}
return d[k][*N+n]==INF?-:d[k][*N+n];
}
void build(int rt,int l,int r){
if(l==r){
add(N*+l,rt,);
add(rt+*N,N*+l,);
return;
}
int mid=(l+r)>>;
build(rt<<,l,mid);
build(rt<<|,mid+,r);
add(rt<<,rt,),add(rt<<|,rt,);
add(rt+*N,*N+rt*,),add(rt+*N,*N+rt*+,);
}
int now,w;
void treeadd1(int rt,int l,int r,int x,int y){
if(x<=l&&r<=y){
add(rt,now,w);
return;
}
int mid=(l+r)>>;
if(x<=mid)treeadd1(rt<<,l,mid,x,y);
if(y>mid)treeadd1(rt<<|,mid+,r,x,y);
}
void treeadd2(int rt,int l,int r,int x,int y){
if(x<=l&&r<=y){
add(now,rt+*N,);
return;
}
int mid=(l+r)>>;
if(x<=mid)treeadd2(rt<<,l,mid,x,y);
if(y>mid)treeadd2(rt<<|,mid+,r,x,y);
}
int main(){
scanf("%d%d%d%d",&n,&n,&m,&k);
memset(head,-,sizeof(head));
edge.clear();
build(,,n);
now=*N;
for(int i=;i<=m;++i){
int a,b,c,d;
scanf("%d%d%d%d%d",&a,&b,&c,&d,&w);
++now;
treeadd1(,,n,a,b);
treeadd2(,,n,c,d);
++now;
treeadd1(,,n,c,d);
treeadd2(,,n,a,b);
}
int ans=dij();
if(ans==-)printf("CreationAugust is a sb!\n");
else printf("%d\n",ans);
return ;
}
HDU5669 Road 分层最短路+线段树建图的更多相关文章
- BZOJ4383/LuoGuP3588  Pustynia/PUS 线段树建图优化
		
我会告诉你我看了很久很久才把题目看懂吗???怀疑智商了 原来他给的l,r还有k个数字都是下标... 比如给了一个样例 l, r, k, x1,x2,x3...xk,代表的是一个数组num[l]~num ...
 - Codeforces Round #406 (Div. 1) B. Legacy 线段树建图跑最短路
		
B. Legacy 题目连接: http://codeforces.com/contest/786/problem/B Description Rick and his co-workers have ...
 - 【转】Codeforces Round #406 (Div. 1) B. Legacy 线段树建图&&最短路
		
B. Legacy 题目连接: http://codeforces.com/contest/786/problem/B Description Rick and his co-workers have ...
 - Codeforces Round #406 (Div. 2) D. Legacy (线段树建图dij)
		
D. Legacy time limit per test 2 seconds memory limit per test 256 megabytes input standard input out ...
 - POJ 2374 线段树建图+Dijkstra
		
题意: 思路: 线段树+Dijkstra(要堆优化的) 线段树要支持打标记 一个栅栏 拆成两个点 :左和右 新加一个栅栏的时候 看看左端点有没有被覆盖过 如果有的话 就分别从覆盖的那条线段的左右向当前 ...
 - BZOJ3073 [Pa2011]Journeys[最短路—线段树优化建边]
		
新技能get✔. 线段树优化建边主要是针对一类连续区间和连续区间之间建边的题,建边非常的优秀.. 这题中,每次要求$[l1,r1]$每一点向$[l2,r2]$每一点建无向边,然后单元最短路. 暴力建边 ...
 - CF-787D-线段树建图+最短路
		
http://codeforces.com/problemset/problem/787/D 题目大意是给出一个有向图,有N个节点,初始节点在S,询问S到所有点最短路.边的读入方式有三种, 1 u v ...
 - [BZOJ4699]树上的最短路(最短路+线段树)
		
https://www.cnblogs.com/Gloid/p/10273902.html 这篇文章已经从头到尾讲的非常清楚了,几乎没有什么需要补充的内容. 首先$O(n\log^2 n)$的做法比较 ...
 - [TJOI2012]桥(最短路+线段树)
		
有n个岛屿, m座桥,每座桥连通两座岛屿,桥上会有一些敌人,玩家只有消灭了桥上的敌人才能通过,与此同时桥上的敌人会对玩家造成一定伤害.而且会有一个大Boss镇守一座桥,以玩家目前的能力,是不可能通过的 ...
 
随机推荐
- Flexbox完整指南- A Complete Guide to Flexbox
			
背景 Flexbox 布局 (FLexible Box)模块(现在处于W3C的最终征求意见稿(Last Call Working Draft)阶段)意在提供一个更为有效的方式来进行布局.对齐和分配一个 ...
 - html5新增标签兼容性
			
很多低版本的浏览器是不识html5新增的标签的,所以为了解决浏览器兼容性问题,主要有两种方法: js可以创建我们自定义的标签,例如,我们可以用js语句 document.createElement(' ...
 - JAVA 修改 JSESSIONID
			
@Action("sidTest") public void sidTest() { HttpSession session = request.getSession(); Str ...
 - mysql更改默认存储引擎
			
在mysql的官网上看到在mysql5.5以上的版本中已经更改了默认的存储引擎,在5.5版本以前是Myisam以后是Innodb. InnoDB as the Default MySQL Storag ...
 - PHP提取身份证号码中的生日并验证是否成年的函数
			
php 提取身份证号码中的生日日期以及确定是否成年的一个函数.可以同时确定15位和18位的身份证,经本人亲测,非常好用,分享函数代码如下: <?php //用php从身份证中提取生日,包括15位 ...
 - 【Druid】 阿里巴巴推出的国产数据库连接池com.alibaba.druid.pool.DruidDataSource
			
阿里巴巴推出的国产数据库连接池,据网上测试对比,比目前的DBCP或C3P0数据库连接池性能更好 简单使用介绍 Druid与其他数据库连接池使用方法基本一样(与DBCP非常相似),将数据库的连接信息 ...
 - 【面试题】百度糯米java工程师面试
			
面试经历: 技术题问的比较基础的java知识,有个编程题设计团购秒杀方面的设计,之前没有这种经验做的不好,做完题一个技术经理过来面试,主要问了一下之前做的什么项目,对struts,spring的原理做 ...
 - Lucene基础(一)--入门
			
Lucene介绍 lucene的介绍,这里引用百度百科的介绍Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,即它不是一个完整的全文检索引 ...
 - 使用KVC
			
KVC是Key Value Coding的简称,意思是键值编码,号称Cocoa的大招.它是一种可以直接通过字符串key(对象在名称)来访问或修改对象属性的机制. 使用 1.利用KVC可以随意修改一个对 ...
 - posix和system v有什么区别/?
			
posix和system v有什么区别/?现在在应用时应用那一标准浮云484212 | 浏览 243 次 2014-11-06 10:362014-11-19 22:36 最佳答案们是有关信号量的两组 ...