题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5956

题意:一颗树上每条边有个权值,每个节点都有新闻要送到根节点就是1节点,运送过程中如果不换青蛙就是走过的所有边权之和的平方,如果换就每次更换要加上P,也就是求“每个节点到根节点这段路径切分成几块之后 [每块的权值和的平方加上(块个数-1)*P] 的最小值”。然后找到所有节点中消耗最大的那个是多少。

题解:设 dist[ i ] 表示节点 i 到根节点的距离,有 dp[ i ] = min(dp[ j ] + ( dist[ i ] - dist[ j ] ) ^ 2 + p),显然是斜率dp,需要注意的是这是在树上做斜率dp,当遍历了一个节点的某一棵子树后,遍历该节点的下一棵子树要恢复到之前的状态,可以考虑 dfs 过程中多传两个参数代表当前队列的 head 和 tail,而遍历完一棵子树后可能改变的是 tail,所以在比遍历之前把 tail 的节点记录下来即可。

 #include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset((a),(b),sizeof(a))
#define mp(a,b) make_pair(a,b)
#define pi acos(-1)
#define pii pair<int,int>
#define pb push_back
const int INF = 0x3f3f3f3f;
const double eps = 1e-;
const int MAXN = 1e5 + ;
const int MAXM = 1e3 + ;
const ll mod = ; int n;
ll p,ans;
vector<pair<int,ll> >vec[MAXN];
ll dist[MAXN],dp[MAXN];
int q[MAXN]; ll sqr(ll x) {
return x * x;
} ll getup(int j,int k) {
return dp[j] + sqr(dist[j]) - (dp[k] + sqr(dist[k]));
} ll getdown(int j,int k) {
return 2ll * (dist[j] - dist[k]);
} void dfs(int u,int fa,int st,int en) {
dp[u] = dist[u] * dist[u];
int head = st, tail = en;
while(head + < tail && getup(q[head + ],q[head]) <= dist[u] * getdown(q[head + ],q[head])) head++;
dp[u] = min(dp[u], dp[q[head]] + sqr(dist[u] - dist[q[head]]) + p);
while(head + < tail && getup(u,q[tail - ]) * getdown(q[tail - ],q[tail - ]) <= getup(q[tail - ],q[tail - ]) * getdown(u,q[tail - ]))
tail--;
q[tail++] = u;
int pre = u;
ans = max(ans, dp[u]);
for(int i = ; i < vec[u].size(); i++) {
int v = vec[u][i].first;
ll w = vec[u][i].second;
if(v == fa) continue;
dist[v] = dist[u] + w;
dfs(v,u,head,tail);
}
q[tail - ] = pre;
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
#endif
int t;
scanf("%d",&t);
while(t--) {
scanf("%d%lld",&n,&p);
for(int i = ; i <= n; i++) {
vec[i].clear();
}
for(int i = ; i < n; i++) {
int u,v;
ll w;
scanf("%d%lld%lld",&u,&v,&w);
vec[u].push_back(make_pair(v,w));
vec[v].push_back(make_pair(u,w));
}
dist[] = ;
int head = , tail = ;
q[tail++] = ;
ans = ;
dfs(,,,);
printf("%lld\n",ans);
}
return ;
}

ACM-ICPC 2016 沈阳赛区现场赛 I. The Elder && HDU 5956(斜率DP)的更多相关文章

  1. ACM-ICPC 2017 沈阳赛区现场赛 M. Wandering Robots && HDU 6229(思维+期望)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6229 参考题解:https://blog.csdn.net/lifelikes/article/det ...

  2. 2016 ACM/ICPC亚洲区青岛站现场赛(部分题解)

    摘要 本文主要列举并求解了2016 ACM/ICPC亚洲区青岛站现场赛的部分真题,着重介绍了各个题目的解题思路,结合详细的AC代码,意在熟悉青岛赛区的出题策略,以备战2018青岛站现场赛. HDU 5 ...

  3. HDU 4046 Panda (ACM ICPC 2011北京赛区网络赛)

    HDU 4046 Panda (ACM ICPC 2011北京赛区网络赛) Panda Time Limit: 10000/4000 MS (Java/Others)    Memory Limit: ...

  4. ACM总结——2017ACM-ICPC北京赛区现场赛总结

    现在距离比赛结束已经过了一个多星期了,也是终于有时间写下心得了.回来就是被压着做项目,也是够够的. 这次比赛一样是我和两个学弟(虽然是学弟,但我的实力才是最弱的T_T)一起参加的,成绩的话打铁,算是情 ...

  5. [刷题]ACM/ICPC 2016北京赛站网络赛 第1题 第3题

    第一次玩ACM...有点小紧张小兴奋.这题目好难啊,只是网赛就这么难...只把最简单的两题做出来了. 题目1: 代码: //#define _ACM_ #include<iostream> ...

  6. ACM-ICPC 2016 大连赛区现场赛 K. Guess the number && HDU 5981(思维+DP)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5981 题意:A在[L, R]之间随机选取一个数X,之后B来猜这个数,如果猜的数比X小,那么A就告诉B猜 ...

  7. ACM-ICPC 2015 沈阳赛区现场赛 I. Triple && HDU 5517(二维BIT)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5517 题意:有二元组(a,b),三元组(c,d,e).当b == e时它们能构成(a,c,d)然后,当 ...

  8. ACM-ICPC 2015 沈阳赛区现场赛 F. Frogs && HDU 5514(容斥)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5514 题意:有m个石子围成一圈, 有n只青蛙从跳石子, 都从0号石子开始, 每只能越过xi个石子.问所 ...

  9. ACM-ICPC 2017 沈阳赛区现场赛 G. Infinite Fraction Path && HDU 6223(BFS)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6223 参考题解:https://blog.csdn.net/qq_40482495/article/d ...

随机推荐

  1. 自学电脑游戏第三天(Swing组件)

    Swing组件 1.按钮(Jbutton) 示例:选择用户所喜欢的城市. import java.awt.*; import java.awt.event.*; import javax.swing. ...

  2. 《剑指offer》查找二维数组内元素 c++

    在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序. 请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. cl ...

  3. 1、Ubuntu linux下同步windows火狐foxfire 浏览器收藏夹问题

    最近在ubuntu系统中使用自带的firefox浏览器,发现有一些问题,比如登陆后,书签,历史记录等,原本在windows下同步的数据无法同步,添加书签的功能也无法使用. 经过查询资料后得知,unbu ...

  4. java源码--Vector和Stack

    一.Vector简介 1.1.Vector概述 通过API中可以知道: 1)Vector是一个可变化长度的数组 2)Vector增加长度通过的是capacity和capacityIncrement这两 ...

  5. NOIP比赛中如何加速c++的输入输出

    NOIP比赛中如何加速c++的输入输出 在竞赛中,遇到大数据时,往往需要更快的读取方式.由于比赛中输出一般规模较小,本文只讨论输入如何加速. 现在我们生成1000000个随机数,构成1000*1000 ...

  6. 迁移WordPress

    一.迁移目的 WordPress是一款能让您建立出色网站.博客或应用的开源软件.官网:https://cn.wordpress.org/download/,最开始是将WordPress部署在本地虚拟机 ...

  7. Go-函数高级使用-条件分支-包管理-for循环-switch语句-数组及切片-与或非逻辑符

    目录 科普 python 注释 # 函数高级 if else if else 包管理 下载第三方包 比较热门的框架 for 循环 for 循环的几种写法 switch 语句 数组及数组切片 数组迭代 ...

  8. RBAC授权

    RBAC RBAC使用rbac.authorization.k8s.io API Group 来实现授权决策,允许管理员通过 Kubernetes API 动态配置策略,要启用RBAC,需要在 api ...

  9. python基础知识0-1

    绝对值:abs age = -19 age.__abs__() 19 相加: add age.__add__() 与运算:and age.__add__() 比较两个数大小:cmp age._cmp_ ...

  10. MyEclipse10.0 采用插件方式安装 SVN

    一.到官方上下载svn1.8.3,下载后的文件名叫site-1.8.3.zip 地址:http://subclipse.tigris.org/servlets/ProjectDocumentList? ...