题意

给一个\(n\)个点的图,标号为\(1\)到\(n\),进行\(m\)次连边\((a,b,c,d,w)\):

for i in range[a,b]:
for j in range[c,d]:
add_edge(i,j,w)

有\(K\)次机会可以消除一条边的权值(即走过但不算),问\(1\)到\(n\)的最短路。

\(n\le 5\times 10^4,m\le 10^4,0\le K\le 10,w\le 10^3\)

分析

\(K\)次消除机会用一个类似dp的东西处理(也被叫做分层图最短路),\(d[i][j]\)表示从1走到\(i\)点用了\(j\)次机会的最短路,显然这个东西是可以dp的。现在我们只需要考虑如何求最短路。

这个连边方式是区间对区间连同一种边,跟bzoj3218的可持久化线段树维护网络流的连边有点像。考虑线段树。

一个区间可以表示为线段树上的最多\(\log n\)个节点。我们一开始给线段树编号,用它来维护连边不就好啦!

一开始是这样想的,但其实只开一颗线段树是不对的,因为无法上下走,于是取看题解。

我们有两颗线段树,一颗连出去,一颗连入,分别称为出线段树和入线段树。出线段树的子节点连到父亲,入线段树的父亲连到子节点。然而如果只是这样的话,我们只能走一条边——从入线段树的某个点走到出线段树的点之后就回不来了!

所以我们把入线段树的每个点连到出线段树的相同位置的点即可。

每次连边是否需要\(\log ^2n\)条边呢?其实不需要,我们可以对每次连边建一个中间节点,出入线段树分别连出,从这个点连入即可。

这样总点数是\(4n+m\),总边数最大为\(2m\log n+6n\),所以使用优先队列优化Dijkstra求最短路,总复杂度为\(O(Km\log ^2n)\) 。

这题学习了两个线段树维护出入以及中间节点减少边数的方法(可能还有分层图最短路吧)。

代码

#include<cstdio>
#include<cctype>
#include<cstring>
#include<queue>
#include<utility>
#include<algorithm>
using namespace std;
int read() {
int x=0,f=1;
char c=getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
for (;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
const int maxn=5e4+1;
const int maxm=1e4+1;
const int maxp=4e5+1;
const int maxe=2e6+1;
const int maxk=11;
int n,m,k,ids=0,d[maxk][maxp],inf;
typedef pair<int,pair<int,int> > data;
inline int Min(int &x,int y) {x=min(x,y);}
priority_queue<data,vector<data>,greater<data> > q;
struct Graph {
struct edge {
int v,w,nxt;
} e[maxe];
int h[maxp],tot;
Graph ():tot(0) {}
void add(int u,int v,int w) {
e[++tot]=(edge){v,w,h[u]};
h[u]=tot;
}
void dj(int S,int T) {
d[0][S]=0;
q.push(make_pair(0,make_pair(S,0)));
while (!q.empty()) {
data dat=q.top();
q.pop();
int x=dat.second.first,tim=dat.second.second;
for (int i=h[x],v=e[i].v;i;i=e[i].nxt,v=e[i].v) {
if (tim<k && d[tim+1][v]>d[tim][x]) {
d[tim+1][v]=d[tim][x];
q.push(make_pair(d[tim+1][v],make_pair(v,tim+1)));
}
if (d[tim][v]>d[tim][x]+e[i].w) {
d[tim][v]=d[tim][x]+e[i].w;
q.push(make_pair(d[tim][v],make_pair(v,tim)));
}
}
}
}
} G;
struct SGT {
int id[maxn<<2];
void build(int x,int l,int r,bool op) {
id[x]=++ids;
if (l==r) return;
int mid=(l+r)>>1;
build(x<<1,l,mid,op),build(x<<1|1,mid+1,r,op);
op?(G.add(id[x],id[x<<1],0),G.add(id[x],id[x<<1|1],0)):(G.add(id[x<<1],id[x],0),G.add(id[x<<1|1],id[x],0));
}
void link(int x,int L,int R,int l,int r,int p,int w,bool op) {
if (L==l && R==r) {
op?G.add(p,id[x],w):G.add(id[x],p,w);
return;
}
int mid=(L+R)>>1;
if (r<=mid) link(x<<1,L,mid,l,r,p,w,op); else
if (l>mid) link(x<<1|1,mid+1,R,l,r,p,w,op); else
link(x<<1,L,mid,l,mid,p,w,op),link(x<<1|1,mid+1,R,mid+1,r,p,w,op);
}
int ID(int x,int l,int r,int p) {
if (l==r) return id[x];
int mid=(l+r)>>1;
return p<=mid?ID(x<<1,l,mid,p):ID(x<<1|1,mid+1,r,p);
}
} a,b;
int main() {
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
#endif
read(),n=read(),m=read(),k=read();
a.build(1,1,n,false);
int tmp=ids;
b.build(1,1,n,true);
for (int i=1;i<=tmp;++i) G.add(tmp+i,i,0);
while (m--) {
int l1=read(),r1=read(),l2=read(),r2=read(),w=read();
++ids;
a.link(1,1,n,l1,r1,ids,w,false);
b.link(1,1,n,l2,r2,ids,0,true);
++ids;
a.link(1,1,n,l2,r2,ids,w,false);
b.link(1,1,n,l1,r1,ids,0,true);
}
memset(d,0x3f,sizeof d),inf=d[0][0];
int S=a.ID(1,1,n,1),T=b.ID(1,1,n,n);
G.dj(S,T); // d[S][0]=0
int ans=inf;
for (int i=0;i<=k;++i) Min(ans,d[i][T]);
ans==inf?puts("Yww is our red sun!"):printf("%d\n",ans);
return 0;
}

HDU5669-Road的更多相关文章

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

    分析:(官方题解) 首先考虑暴力,显然可以直接每次O(n^2) ​的连边,最后跑一次分层图最短路就行了. 然后我们考虑优化一下这个连边的过程 ,因为都是区间上的操作,所以能够很明显的想到利用线段树来维 ...

  2. 【Codeforces 738C】Road to Cinema

    http://codeforces.com/contest/738/problem/C Vasya is currently at a car rental service, and he wants ...

  3. POJ 3204 Ikki's Story I - Road Reconstruction

    Ikki's Story I - Road Reconstruction Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 7 ...

  4. Codeforces #380 div2 C(729C) Road to Cinema

    C. Road to Cinema time limit per test 1 second memory limit per test 256 megabytes input standard in ...

  5. dp or 贪心 --- hdu : Road Trip

    Road Trip Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:65536KB Total submit users: 29 ...

  6. HDU 1598 find the most comfortable road(最小生成树之Kruskal)

    题目链接: 传送门 find the most comfortable road Time Limit: 1000MS     Memory Limit: 32768 K Description XX ...

  7. 三分 --- CSU 1548: Design road

    Design road Problem's Link:   http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1548 Mean: 目的:从(0,0)到 ...

  8. hdu 5861 Road 两棵线段树

    传送门:hdu 5861 Road 题意: 水平线上n个村子间有 n-1 条路. 每条路开放一天的价格为 Wi 有 m 天的操作,每天需要用到村子 Ai~Bi 间的道路 每条路只能开放或关闭一次. ( ...

  9. HDU4081 Qin Shi Huang's National Road System(次小生成树)

    枚举作为magic road的边,然后求出A/B. A/B得在大概O(1)的时间复杂度求出,关键是B,B是包含magic road的最小生成树. 这么求得: 先在原图求MST,边总和记为s,顺便求出M ...

  10. 杭电 1595 find the safest road

    find the safest road Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

随机推荐

  1. 20155317 王新玮 2006-2007-2 《Java程序设计》第4周学习总结

    20155317 王新玮 2006-2007-2 <Java程序设计>第4周学习总结 教材学习内容总结 第六章 继承共同行为 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那 ...

  2. 【LG4585】[FJOI2015]火星商店问题

    [LG4585][FJOI2015]火星商店问题 题面 bzoj权限题 洛谷 \(Notice:\) 关于题面的几个比较坑的地方: "一天"不是一个操作,而是有0操作就相当于一天开 ...

  3. Intellij IDEA 2017 通过scala工程运行wordcount

    首先是安装scala插件,可以通过idea内置的自动安装方式进行,也可以手动下载可用的插件包之后再通过idea导入. scala插件安装完成之后,新建scala项目,右侧使用默认的sbt 点击Next ...

  4. Scratch3.0设计的插件系统(上篇)

    我们每个人在内心深处都怀有一个梦想: 希望创造出一个鲜活的世界,一个宇宙.处在我们生活的中间.被训练为架构师的那些人,拥有这样的渴望: 在某一天,在某一个地方,因为某种原因,创造出了一个不可思议的.美 ...

  5. Linux的10个最危险的命令

    Linux命令行佷有用.很高效,也很有趣,但有时候也很危险,尤其是在你不确定你自己在正在做什么时候. 这篇文章将会向你介绍十条命令,但你最好不要尝试着去使用. 当然,以下命令通常都是在root权限下才 ...

  6. static和构造函数初始化顺序

    abstract class demo{ public demo() {} protected void a() { System.out.println("I am parents!&qu ...

  7. Redis 哨兵 Sentinel

    Redis Sentinel:redis集群应用,分布式系统.   多个Sentinal进程之间通过 gossip 协议来接收主服务器是否下线的信息,通过 Raft 一致性协议来决定故障转移及转移服务 ...

  8. mybatis 加载配置文件的方法

    一.  使用sqlSessionFactory 的 mapperLocations 进行加载 <!-- SessionFactory --> <bean id="sqlSe ...

  9. JavaScript学习笔记(三)——对象

    第四章 理解对象 1 说明 对象的状态:属性,行为:方法: 对象定义放在花括号内: 用冒号分隔属性名和属性值: 用逗号分隔属性名和属性值对,包括方法: 最后一个属性值后面不加逗号: 属性名可以是任何字 ...

  10. rz和sz上传下载文件

    安装软件包 yum install  lrzsz   上传文件,输入rz选择文件上传(可以按住shift键多选) # rz   sz 下载文件到本地,选择保存文件夹 # sz dd   xshell设 ...