HDU 5956 树上进行斜率优化DP + 记录操作并撤销
来源:互联网 发布:java常用api详解 编辑:程序博客网 时间:2024/06/04 18:35
题意:以前,在神秘的大陆,有一个青蛙王国,由最年长的青蛙——长者统治着。这个王国由N座城市组成,从东到西编号。第一座城市是首都,座落在最东边。每一个城市,连接者几个或者没有连接几个西边的城市,并且只连接了一个东边的城市。每天,都有一些大新闻发生在一些城市。长者想尽快地知道。所以,青蛙新闻工作者的工作就是,跑得比其他青蛙都快。当有巨大新闻发生在某座城市的时候,这座城市的新闻工作者将会携带信息,跑向首都。当到达另一个城市的时候,他可以继续跑,也可停下来让其他的新闻工作者传输信息。这些新闻工作者由于太年轻并且简单,不能有效的跑很长的距离。结果,他们需要 L2的时间来跑一条长度为L的路径。除此之外,传达信息需要P的时间,是为了检查传达信息是否有误,因为信息的误差会使长者极度的生气。现在你高兴的收到一个任务:计算从所有城市发送信息到首都的所需的最长的时间。我想问公然膜蛤真的好?
解题思路:可以将图看成一个由1点为根的树,每个点到根结点为路径是唯一的。设dp[u]为u点传输信息到根节点的所需时间。a[u]为u点到根节点的距离。很明显,dp[u] = min{dp[k]+(sum[u]−sum[k])2+P | k是u的祖先)。用斜率优化优化DP转移即可。但是不同的点路径不同,所以这里还需要记录在这个点对于斜率优化的队列操作了什么,回溯离开这个点的时候,需要撤销这些操作,操作每个点有一个栈记录即可。对于从根节点转移吃出来,可以考虑单独转移,也可设置dp[1]=-P。
代码如下:
#include <bits/stdc++.h>using namespace std;#define MP(x, y) make_pair(x, y)typedef long long LL;const int N = 1e5+5;struct fs{ LL fz, fm; fs(){fz = 0, fm = 1;}; fs(LL fz2, LL fm2) : fz(fz2) , fm(fm2) { if(fm < 0){ fz = -fz; fm = -fm; } } bool operator <(const fs &rhs) const{ return fz * rhs.fm < fm * rhs.fz; } bool operator <(const LL rhs) const{ return *this < fs(rhs, 1LL); }};int p[N], cnt;struct edge{ int v, w, nxt; edge(){} edge(int v, int w, int nxt) : v(v), w(w), nxt(nxt) {}}E[N*2];void addedge(int u, int v, int w){ E[cnt].v = v, E[cnt].w = w, E[cnt].nxt = p[u], p[u] = cnt++;}void init(){ memset(p, -1, sizeof(p)); cnt = 0;}void getmax(LL &x, LL y){ if(y > x) x = y;}int head, tail;LL ans, que[N], dp[N], sum[N]; //sum维护前缀和LL P;LL sqr(LL x){ return x * x;}int getDP(int i, int j){ return dp[j] + P + sqr(sum[i] - sum[j]);}fs getxl(int j, int k){ //取斜率 return fs(dp[j] + sqr(sum[j]) - dp[k] - sqr(sum[k]), 2 * (sum[j] - sum[k]));}void dfs(int u, int fa, int len){ sum[u] = sum[fa] + len; //0 pop_front 2 pop_back 3 push_back stack <pair <int, int> > stk; if(u != 1){ while(tail - head >= 2 && getxl(que[head], que[head+1]) < sum[u]) stk.push(MP(0, que[head++])); dp[u] = getDP(u, que[head]); //dp[u] = min(dp[u], sum[u] * sum[u]); while(tail - head >= 2 && getxl(que[tail-1], u) < getxl(que[tail-2], que[tail-1])) stk.push(MP(2, que[--tail])); } que[tail++] = u; stk.push(MP(3, u)); getmax(ans, dp[u]); for(int i = p[u]; ~i; i = E[i].nxt){ int v = E[i].v, w = E[i].w; if(v == fa) continue; dfs(v, u, w); } while(!stk.empty()){ int op = stk.top().first; int v = stk.top().second; stk.pop(); if(op == 0) que[--head] = v; else if(op == 2) que[tail++] = v; else if(op == 3) tail--; else head++; }}int main(){ int T, n; scanf("%d", &T); while(T--){ scanf("%d%lld", &n, &P); init(); memset(sum, 0, sizeof(sum)); for(int i = 1; i < n; i++){ int u, v, w; scanf("%d%d%d", &u, &v, &w); addedge(u, v, w); addedge(v, u, w); } ans = -1; head = tail = 0; dp[1] = -P; dfs(1, 0, 0); printf("%lld\n", ans); } return 0;}
0 0
- HDU 5956 树上进行斜率优化DP + 记录操作并撤销
- HDU 5956 The Elder(树上斜率优化DP)
- bzoj1767 树上dp斜率优化+二分
- 【斜率优化dp】HDU 2993
- hdu 4258(斜率优化DP)
- hdu 3507 斜率优化dp
- HDU 3480 DP+斜率优化
- hdu 2993 斜率优化DP
- hdu 3507 斜率优化DP
- hdu 2829 斜率优化DP
- hdu 3507 斜率优化dp
- hdu 3507 斜率dp优化
- hdu 3507 斜率优化dp
- HDU 3480 斜率优化DP
- hdu 2829 斜率优化DP
- hdu5956 树上斜率DP
- bzoj3672 [ NOI2014 ] -- 树上CDQ分治 + 斜率优化DP
- HDU-5956 The Elder(树型dp+斜率优化)
- c++能使用标准c库
- OpenInventor程序设计从入门到精通目录
- SublimeText3 右键打开
- [LeetCode]474. Ones and Zeroes
- 算法提高 6-17复数四则运算
- HDU 5956 树上进行斜率优化DP + 记录操作并撤销
- 1014. Waiting in Line (30)-PAT甲级真题(queue的应用)
- 浅谈Web建站技术
- 类加载过程代码实例
- Impala源代码学习序
- How to Generate a Good Word Embedding(学习笔记)
- Java:String和Date、Timestamp之间的转换
- javascript流程控制、循环控制
- CPU/内存/缓存行/Disruptor