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镇守一座桥,以玩家目前的能力,是不可能通过的 ...
随机推荐
- DataNavigator之分页
前言 做客户端也有两个月了,先前做列表都没有分页,可能考虑数据也不是很多,昨天做了一个页面,考虑到了数据的问题,所以改为分页查询.因为也是第一次用dev,用哪个控件分页呢,还是要去搜一下,得出的事Da ...
- c语言贪吃蛇
思路:函数gotoxy(x,y)使光标移植屏幕的x,y坐标(屏幕左上角为0,0),用来绘制蛇和界面,color()函数用来设置绘制的颜色.设有snakelong节,第i节蛇的x坐标为x[i],y坐标为 ...
- linux之vim编辑器
Vi简介1. Vi是一种广泛存在于各种UNIX和Linux系统中的文本编辑程序.2. Vi不是排版程序,只是一个纯粹的文本编辑程序.3. Vi是全屏幕文本编辑器,它没有菜单,只有命令.4. Vi不是基 ...
- linux下使用split 来分割大文件
linux下使用split 来分割大文件 2010-07-27 15:46:27| 分类: 技术文稿 | 标签:split 分割 linux |字号 订阅 平常都是使用ssh来进行远程 ...
- 【单片机通信协议】CAN总线基础知识
CAN总线基础知识(一) 1.1 CAN总线是什么? CAN(Controller Area Network)是ISO国际标准化的串行通信协议.广泛应用于汽车.船舶等.具有已经被大家认可的高性能和可靠 ...
- Oracle删除所有表
Oracle 清理用户所有的表 PLSQL中执行语句 select 'drop '||object_type||' '||object_name||';' from user_objects; 结果集 ...
- C# and JSON
JQuery Parse JSON var obj = $.parseJSON(data); C# creates JSON string: public static class JSONHelpe ...
- Python属性、方法和类管理系列之----属性初探
在学习dict的时候,肯定听过dict是Python中最重要的数据类型,但是不一定知道为什么.马上你就会明白原因了. Python中从模块.到函数.到类.到元类,其实主要管理方法就是靠一个一个的字典. ...
- Ubuntu之网络配置
一.配置大概分三类:通过配置文件配置.通过命令配置.通过图形化的网络连接菜单配置. 拨号无线等的没条件实验,不涉及. 主要文件:/etc/network/interfaces,这里是IP.网关.掩码等 ...
- zepto源码学习-05 ajax
学习zeptoajax之前需要先脑补下,强烈推荐此文http://www.cnblogs.com/heyuquan/archive/2013/05/13/js-jquery-ajax.html 还有A ...