E. Long Way Home
斜率优化dp,dijkstra

题意

给定一个 n n n 个点, m m m 条边的带权无向图,边形如 < u , v , w > <u, v, w> <u,v,w> ,起点为 1 1 1 。可以乘坐至多 k k k 次飞机,从 u u u 到 v v v ,距离为 ( u − v ) 2 (u - v) ^ 2 (u−v)2 。求到每个点的最短距离。 ( n , m ≤ 1 e 5 , k ≤ 20 ) (n, m\leq 1e5, k\leq 20) (n,m≤1e5,k≤20)

思路

当 k = 0 k = 0 k=0 时,dijkstra即可求出最短路,考虑 k = 1 k=1 k=1 时如何求。
一个显而易见的做法是在 k = 0 k=0 k=0 的基础上,枚举哪两个点之间坐了飞机。

for(int i = 1; i <= n; i++) {for(int j = 1; j <= n; j++) {dis[i] = min(dis[i], old_dis[j] + (u - v)*(u - v));}
}

当然,不一定是最后一步才坐飞机,所以更新 d i s dis dis 后仍需要跑一遍dijkstra,可以得到答案。
于是我们得到了 O ( k n 2 ) O(kn^2) O(kn2) 的做法。
由于 k k k 范围很小,给了我们提示:从 0 , 1 , 2 , . . . k − 1 0,1,2,...k-1 0,1,2,...k−1 一直枚举到 k k k ,所以考虑如何优化上述转移。
将上述转移写为数学表达式
d i s [ v ] = m i n u ∈ [ 1 , n ] ( o l d _ d i s [ u ] + ( u − v ) 2 ) = o l d _ d i s [ u ] + u 2 + v 2 − 2 × u × v dis[v] = min_{u\in[1, n]} (old\_dis[u] + (u - v) ^ 2)=old\_dis[u] + u^2 + v^2 -2\times u\times v dis[v]=minu∈[1,n]​(old_dis[u]+(u−v)2)=old_dis[u]+u2+v2−2×u×v
上式中,因为有 u × v u\times v u×v 的项,考虑斜率优化。
设 k = − 2 u , b = o l d _ d i s [ u ] + u 2 , f ( v ) = k v + b k=-2u, b=old\_dis[u]+u^2,f(v)=kv+b k=−2u,b=old_dis[u]+u2,f(v)=kv+b ,则原式转化为 d i s [ v ] = f ( v ) + v 2 dis[v]=f(v) + v^2 dis[v]=f(v)+v2 。
其中 f ( v ) f(v) f(v) 即为所维护的斜率,因为我们需要让 f ( v ) f(v) f(v) 尽可能小,所以我们维护一个下凸包。
时间复杂度 O ( k ( m l o g n + n l o g n ) ) O(k(mlogn + nlogn)) O(k(mlogn+nlogn))
也可以优化到 O ( k ( m l o g n + n ) ) O(k(mlogn + n)) O(k(mlogn+n)) ,由于询问1-n满足单调性,所以不需要二分。

代码

struct line {int k, b;line() {}line(int k, int b) : k(k), b(b) {}double intersect(line l) {//交点double db = l.b - b;double dk = k - l.k;return db / dk;}int operator () (int x) {return k * x + b;}bool operator < (const line x) const {return k > x.k;}
};struct CHT {vector<double> x;vector<line> lines;void init(line l) {x.push_back(-INF);lines.push_back(l);}void addLine(line l) {while (lines.size() >= 2 && l.intersect(lines[lines.size() - 2]) <= x.back()) {x.pop_back();lines.pop_back();}x.push_back(l.intersect(lines.back()));lines.push_back(l);}int query(int qx) {int id = upper_bound(x.begin(), x.end(), qx) - x.begin();--id;return lines[id](qx);}
};
struct node {int dis, pos;bool operator <(const node &x)const {return x.dis < dis;}
};
const int MAXN = 1e5 + 5;
struct edge {int v, w;};
vector<edge>g[MAXN];
int dis[MAXN];
bool vis[MAXN];
int n, m, k;
void Dij() {for (int i = 1; i <= n; i++)vis[i] = 0;priority_queue<node>que;for (int i = 1; i <= n; i++)que.push({ dis[i],i });while (que.size()) {auto x = que.top(); que.pop();int u = x.pos, distance = x.dis;if (vis[u])continue;vis[u] = 1;for (edge ed : g[u]) {int v = ed.v, w = ed.w;if (dis[v] > distance + w) {dis[v] = distance + w;if (!vis[v])que.push({ dis[v],v });}}}
}
void solve() {cin >> n >> m >> k;for(int i = 1; i <= m; i++) {int u, v, w;cin >> u >> v >> w;g[u].pb({v, w});g[v].pb({u, w});}for(int i = 1; i <= n; i++) {dis[i] = INF;}dis[1] = 0;Dij();while(k--) {CHT cht;cht.init({0, 0});vector<line> lines;for(int u = 1; u <= n; u++)lines.pb({- 2 * u, dis[u] + u * u});sort(lines.begin(), lines.end());for(auto l : lines)cht.addLine(l);for(int v = 1; v <= n; v++)dis[v] = cht.query(v) + v * v;Dij();}for(int i = 1; i <= n; i++) {cout << dis[i] << ' ';}cout << endl;
}

#816 Div2E. Long Way Home 斜率优化dp相关推荐

  1. NOI2007 货币兑换 - CDQ分治斜率优化dp

    斜率优化dp维护一个凸壳.如果\(x, y\)坐标都递增,可以用单调队列,如果只有\(x\)递增,可以在凸壳上二分斜率,如果\(x, y\)都不递增,则需要在凸包中插入,可以用平衡树或cdq分治维护. ...

  2. CF-311B Cats Transport(斜率优化DP)

    题目链接 题目描述 小S是农场主,他养了 \(M\)只猫,雇了 \(P\) 位饲养员. 农场中有一条笔直的路,路边有 \(N\) 座山,从 \(1\) 到 \(N\)编号. 第 \(i\) 座山与第 ...

  3. 【洛谷3648】[APIO2014] 序列分割(斜率优化DP)

    点此看题面 大致题意: 你可以对一个序列进行\(k\)次分割,每次得分为两个块元素和的乘积,求总得分的最大值. 区间\(DPor\)斜率优化\(DP\) 这题目第一眼看上去感觉很明显是区间\(DP\) ...

  4. HDU-3507Print Article 斜率优化DP

    学习:https://blog.csdn.net/bill_yang_2016/article/details/54667902 HDU-3507 题意:有若干个单词,每个单词有一个费用,连续的单词组 ...

  5. APIO2010 特别行动队 斜率优化DP算法笔记

    做完此题之后 自己应该算是真正理解了斜率优化DP 根据状态转移方程$f[i]=max(f[j]+ax^2+bx+c),x=sum[i]-sum[j]$ 可以变形为 $f[i]=max((a*sum[j ...

  6. HDU 3507 Print Article(斜率优化DP)

    题目链接 题意 : 一篇文章有n个单词,如果每行打印k个单词,那这行的花费是,问你怎么安排能够得到最小花费,输出最小花费. 思路 : 一开始想的简单了以为是背包,后来才知道是斜率优化DP,然后看了网上 ...

  7. HDU 2993 MAX Average Problem(斜率优化DP)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2993 题目大意:给定一个长度为n(最长为10^5)的正整数序列,求出连续的最短为k的子序列平均值的最大 ...

  8. YBTOJ洛谷P3195:玩具装箱(斜率优化dp)

    传送门 文章目录 前言 解析 代码 前言 斜率优化dp,就是利用斜率优化的dp (逃) 解析 第一道斜优的题 分析题目 设sumisum_isumi​为1-i的c的前缀和 容易写出dp转移式: dpi ...

  9. bzoj1010[HNOI2008]玩具装箱toy 斜率优化dp

    1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 11893  Solved: 5061 [Submit] ...

最新文章

  1. Java学习笔记二十五:Java面向对象的三大特性之多态
  2. Ubuntu下用webstorm开发Nodejs(二)
  3. Memcached通用类(基于enyim.com Memcached Client)
  4. webso员ket php,客戶端和PHP後端通信:Sokets,Stream,TCP/UDP?
  5. 苹果cmsv10播放器源码插件
  6. vs code怎么编译C语言,Visual Studio Code 如何编写运行 C、C++ 程序?
  7. bzoj 1057: 棋盘制作(悬线法)
  8. SWPU第二届天梯选拔赛暨蓝桥杯训练赛题解
  9. 机器学习常用算法总结
  10. poj 1113 graham模板(水平序)
  11. 小学数学测试软件前言,小学数学教学案例集序言.docx
  12. 微星主板黑苹果_黑苹果安装教程:准备磁盘+主板BIOS设置——墨涩网
  13. win7局域网共享设置_局域网硬盘一键共享软件下载-一键共享局域网修复查看设置工具包免费版...
  14. php 公众号推送图片尺寸,微信公众号推送文图片什么尺寸最佳?
  15. PR视频剪辑(项目包装)
  16. 获取安卓模拟器的型号(品牌)
  17. 台湾 天堂java 论坛_tiantangsifu_Rev1388jar_1386db java编写天堂私服*系统 - 下载 - 搜珍网...
  18. 144hz和60hz测试软件,关于显示器,60hz与144hz,以个人角度,给大家分享心得…
  19. 小程序——切割字符串
  20. 时间转换——Java

热门文章

  1. Linux 日志分析工具之awstats详解
  2. tar命令打包分割文件
  3. 本文是对优雅草蜻蜓C影视便捷追剧小程序微信支付配置教程-大部分小程序支付通用,从微信配置到后台的详解,其他小程序系统均可参考
  4. 程序员的自我修养—链接、装载与库--书签目录PDF
  5. 剥皮抽筋, 细解USB CONSOLE线到底是不是原装FTDI芯片线
  6. wap2app 安卓返回键 直接退出问题
  7. 含含乐代理为球场运动员提供吸烟替代解决方案
  8. 数据库实验一 数据库定义及数据导入
  9. yolov4 网络结构解析
  10. Winscp连接Amazon Ec2实例传送文件