hdu 5669 Road
题目大意
\(n\)个点,\(m\)次连边
每次连边为\((a\sim b)\leftrightarrow (c\sim d),cost=w\)
即在\((a-b)\)区间内的点向\((c-d)\)区间内的点,两两连一条费用w的双向边
给出\(k\)次机会使一条边费用为\(0\)
求\(1-n\)的最短路
分析
暴力连边\(O(mn^2)\)显然不行
既然是区间连边,是否可以用线段树的方法把区间拆成log个呢
做法
考虑一颗线段树
每次把提取出的\(log\)个区间\(log^2\)连边
然后考虑走到一个线段上
如果线段上每一个点都在当前到达集合,那么可以往下走
由于父亲一定包含当前点,所以可以往上走
但这样分类讨论难以实现
考虑两棵线段树
连边 第一颗树连向第二棵树
第一棵树只能往上走
第二棵树只能往下走
然后第二棵树上的线段连一条边指回第一棵树的对应节点
源点放在第一棵树
汇点放在第二棵树
可以发现,跳完一条边后即到了第二棵树,此时线段上每个点都在可达集合,可以往下走,然后跳回第一棵树,继续走边
是符合要求的
最后考虑回一开始的连边,\(log^2\)的连边跑起dijkstra还是很炸的
但是我们可以强行加一个中间节点,这样边数就变成\(log\)了
连完边跑分层图最短路即可
连边复杂度\(O(m\log n)\)
dijkstra复杂度\(O(m\log^2 n)\)
solution(代码较挫)
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <cmath>
#include <queue>
using namespace std;
const int M=131077;
const int N=890035;
const int INF=2139062143;
inline int ri(){
int x=0;bool f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
for(;isdigit(c);c=getchar()) x=x*10+c-48;
return f?x:-x;
}
int tcas,n,m,lim,id,S,T;
struct vec{
int g[M<<2],te;
struct edge{
int y,d,nxt;
edge(int _y=0,int _d=0,int _nxt=0){y=_y,d=_d,nxt=_nxt;}
}e[N];
vec(){memset(g,0,sizeof g);te=0;}
inline void push(int x,int y,int d=0){e[++te]=edge(y,d,g[x]);g[x]=te;}
inline int& operator () (int x){return g[x];}
inline edge& operator [] (int x){return e[x];}
}e;
struct segment{
int lc[M<<1],rc[M<<1],fa[M<<1],tot,rt;
segment(){
memset(lc,0,sizeof lc);
memset(rc,0,sizeof rc);
tot=0;rt=0;
}
int build(int l,int r){
int x=++tot;
if(l==r) return x;
int mid=l+r>>1;
lc[x]=build(l,mid);
rc[x]=build(mid+1,r);
fa[lc[x]]=x;
fa[rc[x]]=x;
return x;
}
int find(int x,int l,int r,int to){
if(l==r) return x;
int mid=l+r>>1;
if(to<=mid) return find(lc[x],l,mid,to);
return find(rc[x],mid+1,r,to);
}
int find(int x){return find(rt,1,n,x);}
void toid(int x,int l,int r,int tl,int tr,int id,int d){
if(tl<=l&&r<=tr){
e.push(x,id,d);
return;
}
int mid=l+r>>1;
if(tl<=mid) toid(lc[x],l,mid,tl,tr,id,d);
if(mid<tr) toid(rc[x],mid+1,r,tl,tr,id,d);
}
void idto(int x,int l,int r,int tl,int tr,int id,int d){
if(tl<=l&&r<=tr){
e.push(id,x,d);
return;
}
int mid=l+r>>1;
if(tl<=mid) idto(lc[x],l,mid,tl,tr,id,d);
if(mid<tr) idto(rc[x],mid+1,r,tl,tr,id,d);
}
void toid(int l,int r,int id,int d){
toid(rt,1,n,l,r,id,d);
}
void idto(int l,int r,int id,int d){
idto(rt,1,n,l,r,id,d);
}
}L,R;
void addedge(int u,int v,int x,int y,int d){
++id;
L.toid(u,v,id,d);
R.idto(x,y,id,0);
}
struct node{
int s,x,d;
node(int _s=0,int _x=0,int _d=0){s=_s,x=_x,d=_d;}
bool operator < (const node &y) const{
return d>y.d;
}
};
priority_queue<node>q;
int f[13][M<<2];
void solve(){
memset(f,127,sizeof f);
f[0][S]=0;
q.push(node(0,S,0));
node nw;
int s,x,d,p,y;
while(!q.empty()){
nw=q.top(); q.pop();
s=nw.s; x=nw.x; d=nw.d;
for(p=e(x);p;p=e[p].nxt){
y=e[p].y;
if(d+e[p].d<f[s][y]){
f[s][y]=d+e[p].d;
q.push(node(s,y,f[s][y]));
}
if(s<lim&&d<f[s+1][y]){
f[s+1][y]=d;
q.push(node(s+1,y,f[s+1][y]));
}
}
}
int i,ans=INF;
for(i=0;i<=lim;i++) ans=min(ans,f[i][T]);
if(ans==INF) puts("Yww is our red sun!");
else printf("%d\n",ans);
}
int main(){
int i,u,v,x,y,d;
tcas=ri();
n=ri(),m=ri(),lim=ri();
L.tot=0; L.build(1,n); L.rt=1;
R.tot=L.tot; R.build(1,n); R.rt=L.tot+1;
S=L.find(1); T=R.find(n); id=R.tot;
for(i=L.rt+1;i<=L.tot;i++) e.push(i,L.fa[i]);
for(i=R.rt;i<=R.tot;i++) e.push(i,i-L.tot);
for(i=R.rt+1;i<=R.tot;i++) e.push(R.fa[i],i);
while(m--){
u=ri(),v=ri(),x=ri(),y=ri(),d=ri();
addedge(u,v,x,y,d);
addedge(x,y,u,v,d);
}
solve();
return 0;
}
hdu 5669 Road的更多相关文章
- HDU 5669 Road(线段树建树)(分层图最短路)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5669 [分析]线段树建树+分层图最短路 #include <cstdio> #includ ...
- hdu 5861 Road 两棵线段树
传送门:hdu 5861 Road 题意: 水平线上n个村子间有 n-1 条路. 每条路开放一天的价格为 Wi 有 m 天的操作,每天需要用到村子 Ai~Bi 间的道路 每条路只能开放或关闭一次. ( ...
- HDU 5861 Road (线段树)
Road 题目链接: http://acm.split.hdu.edu.cn/showproblem.php?pid=5861 Description There are n villages alo ...
- HDU 5861 Road 线段树区间更新单点查询
题目链接: http://acm.split.hdu.edu.cn/showproblem.php?pid=5861 Road Time Limit: 12000/6000 MS (Java/Othe ...
- HDU 5861 Road(线段树 区间修改 单点查询)
Road Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submi ...
- HDU 3917 Road constructions(最小割---最大权闭合)
题目地址:HDU 3917 这题简直神题意... 题目本身就非常难看懂不说..即使看懂了.也对这题意的逻辑感到无语...无论了.. 就依照那题意上说的做吧... 题意:给你n个城市,m个公司.若干条可 ...
- 2016 Multi-University Training Contest 10 [HDU 5861] Road (线段树:区间覆盖+单点最大小)
HDU 5861 题意 在n个村庄之间存在n-1段路,令某段路开放一天需要交纳wi的费用,但是每段路只能开放一次,一旦关闭将不再开放.现在给你接下来m天内的计划,在第i天,需要对村庄ai到村庄bi的道 ...
- HDU 5669 线段树优化建图+分层图最短路
用线段树维护建图,即把用线段树把每个区间都标号了,Tree1中子节点有到达父节点的单向边,Tree2中父节点有到达子节点的单向边. 每次将源插入Tree1,汇插入Tree2,中间用临时节点相连.那么T ...
- hdu 3917 Road constructions 最大权闭合子图
样例说明: n(城市数目) m(工程队数目) 每个工程队上交的税收 val[i] k(k个工程) xi yi ci costi , 工程队ci承包由xi到yi,政府的补贴为costi 注意 ...
随机推荐
- 01_14_Struts2_结果类型_result_type
01_14_Struts2_结果类型_result_type 1. result类型 result类型 说明 dispatcher 默认服务端转发jsp chain 服务端action转发 redir ...
- 【转】【win网络编程】socket中的recv阻塞和select的用法
在编写ftp客户端程序时,在联通后使用recv函数进行接收欢迎信息时,需要申请内存进行接收数据保存,一次读取成功,但是由于一个随机的ftp服务端在说,欢迎信息的大小是不知道的,所以在尝试使用死循环,在 ...
- 5-3 time模块
1.取当前时间戳和当前格式化时间 import time1 # 以时间戳的形式打印当前时间 1543849862 print(int(time.time()))#时间戳 # 取当前格式化好的时间 20 ...
- JavaScriptDate(日期)
如何使用Date()方法获取当日的日期. getFullYear(): 使用getFullYear()获取年份. getTime(): getTime()返回1970年1月1日至今的毫秒数. setF ...
- vmware 开机自动启动
vmware开机自动启动, 可以使用vmrun命令. 1. 首先在“我的电脑”-“属性”-“高级”-“环境变量”-“PATH”中添加vmware路径,如:C:\Program Files (x86)\ ...
- MongDB之各种修改操作
接口IMongDaoUpdate: package com.net.test.mongdb.dao; import com.net.test.mongdb.entity.User; public in ...
- Missian指南三:创建一个Missian服务器(使用spring)
在使用Missian时,spring是可选的,但是作者本人强烈推荐和Spring配合使用.Spring是一个伟大的项目,并且它不会对程序在运行时的效率带来任何损耗. Missian在服务器端依赖与Mi ...
- 华东交通大学2018年ACM“双基”程序设计竞赛 D
摸鱼之王MIKU酱想去埃及玩,需要一个人陪同.小新和小磊都想陪MIKU酱一起去,但名额只有一个.所以小磊和小新决定用一个小游戏来决定谁和MIKU酱出去玩. 游戏的道具是21张塔罗牌,塔罗牌分 ...
- python数据模型(特殊方法)
python中的全部特殊方法 本部分内容可以参考官方网址 python中一共有83个特殊方法,其中47个用于算术运算.位运算和比较操作.我根据<流畅的python>中的整理,摘录如下两个表 ...
- Redis实现之复制(二)
PSYNC命令的实现 在Redis实现之复制(一)这一章中,我们介绍了PSYNC命令和它的工作机制,但一直没有说明PSYNC命令的参数以及返回值.现在,我们了解了运行ID.复制偏移量.复制积压缓冲区以 ...