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 注意 ...
随机推荐
- Java中的异常处理从概念到实例
1.概念 采用新的异常处理机制 在以往的程序开发过程中,经常采用返回值进行处理.例如,在编写一个方法,可以返回一个状态代码,调用者根据状态代码判定出错与否.若状态代码表示一个错误,则调用这进行相应的处 ...
- oc描述器排序
int main(int argc, const char * argv[]) { @autoreleasepool { NSArray *array = @[CreateDict(@"王思 ...
- react 的虚拟dom
前端优化的主要方面就是减少页面的DOM操作,减少重排和重绘,React在这方面做了优化,采用了所谓的虚拟DOM,其实我们平时也会遇到虚拟DOM,只是你没有注意罢了,请听我娓娓道来. 所谓的虚拟DOM ...
- SummerVocation_Learning--java的String类运用
题目: 编写一个程序,输出一个字符串中的大写字母数,小写字母数,及其它字母数. 思路1: 可以先遍历整个字符串,在判断每个字符的类型. public class TestString { public ...
- 基于flash-marker.js 的地图标注闪烁代码调试
修改网上流传的flash-marker.js (function (global, factory) { typeof exports === 'object' && typeof m ...
- c#:无限极树形结构
最近一直在研究树形结构菜单,无意中让我弄了出来.先上代码: 首先需要这个的一个类 public class Tree { public int id { get; set; } public stri ...
- Linux 面试的一些基础命令
1.查询服务器负载 (1)uptime [root@oldboy ~]# uptime 20:17:18 up 7:41, 2 users, load average: 0.00, 0.00, 0.0 ...
- Android 自定义 radiobutton
<RadioButton android:id="@+id/radiobutton_pay_method" android:layout_width="30dp&q ...
- Redis实现之字典
字典 字典,又称为符号表(symbol table).关联数组(associative array)或映射(map),是一种用于保存键值对(key-value pair)的抽象数据结构.在字典中,一个 ...
- 极简Node教程-七天从小白变大神(一:你需要Express)
如果说用一句话来概括Node那就是:它开启了JavaScript服务器端语言. Node系列的文章并不会从一开始长篇概论的讲Node的历史,安装,以及其他很琐碎的事情.只会专门介绍关于Node或者准确 ...