题意

给一个\(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. LVS入门篇(二)之LVS基础

    1. LVS介绍 LVS是Linux虚拟服务器(LinuxVirtualServers),使用负载均衡技术将多台服务器组成一个虚拟服务器.它为适应快速增长的网络访问需求提供了一个负载能力易于扩展,而价 ...

  2. 【Unity3d】MenuItem修饰的方法无法触发的可能原因

    遇到了MenuItem修饰的方法无法触发的情况,顺利解决. 类放在Editor目录下,该类下其他方法被MenuItem修饰可以触发. 后来发现我修饰的方法和该类下另一个方法重名了. 改方法名,问题解决 ...

  3. Linux环境配置备忘

    1.Ubuntu服务器版本装scipy 预装版本可能fortran包版本过旧或者不全,安装scipy之前需要更新环境. sudo apt-get install gfortran libopenbla ...

  4. 2019年猪年颁奖典礼、公司年会、跨年晚会、科技会议、年终答谢会之幕布背景展板PSD模板-第三部分

    16套--2019年猪年颁奖典礼.公司年会.跨年晚会.科技会议.年终答谢会之幕布.背景和展板PSD模板,免费颁奖典礼PSD展板背景幕布,下载地址:百度网盘,https://pan.baidu.com/ ...

  5. [C++]boost dijkstra获得两点间的最短路

    需求是只需要得到两点间的最短路,不需要求得单源对于全图的最短路,使用boost中的dijsktra_shortest_path,当得到目标点的最短路时直接throw exception. #inclu ...

  6. phpcms单页顶级栏目默认打开第一个子栏目方法

    首先phpcms单页如过下面有子栏目,那么当前栏目是不能被编辑内容的,且访问后是没有内容的,首先不知道这是不是产品设计的一个缺陷,但是在使用过程中确实在后台也没有找到其他的对应解决办法,刚好在某QQ群 ...

  7. linux云主机小技巧

    微信服务器安装 安装库 python 3.5环境下 pip安装web.py时 会报错 "no module named "utils" 等问题 更换命令为“pip ins ...

  8. kaldi DNN在线解码 aishell为例

    在kaldi 的工具集里有好几个程序可以用于在线识别.这些程序都位在src/onlinebin文件夹里,他们是由src/online文件夹里的文件编译而成(你现在可以用make ext 命令进行编译) ...

  9. PHP 整数

    实验环境php 5.2.17,参考资料:PHP手册 1.整数溢出 如果整数超出最大范围或者运算结果超出最大范围,都会转变成float <?php $a=2147483647; var_dump( ...

  10. Qt中容器类应该如何存储对象

    Qt提供了丰富的容器类型,如:QList.QVector.QMap等等.详细的使用方法可以参考官方文档,网上也有很多示例文章,不过大部分文章的举例都是使用基础类型:如int.QString等.如果我们 ...