题目链接: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 ;
}

最新文章

  1. git init和git init -bare区别
  2. Codeforces Round #364 (Div. 2)
  3. window.frame
  4. xmind的第二天笔记
  5. 数据采集服务提供商,ip提供商 里面有些不错的基础数据
  6. datatable,查询,排序,复制等操作
  7. 通过Camera进行拍照
  8. Linux磁盘分区/格式化/挂载(树莓派3挂载硬盘)
  9. 【CF235C】Cyclical Quest(后缀自动机)
  10. React(一)使用脚手架创建React项目
  11. Beta冲刺 1
  12. 测试工具之Fiddler
  13. nginx使用https协议
  14. https SSL主流数字证书都有哪些格式(转载)
  15. 分布式缓存技术redis系列(三)——redis高级应用(主从、事务与锁、持久化)
  16. swift能干什么,不能干什么及相关概念
  17. Problem A: 道路建设 解题报告
  18. python webdriver api-右键另存下载文件
  19. 一个关于狗记录的Java练习
  20. quartz入门实例

热门文章

  1. js函数(4)闭包
  2. Jmeter对Websocket进行接口压力测试
  3. ROS的初步学习--创建一个工作空间和一个程序包
  4. python 分支语句 等值判断 逻辑运算符
  5. 面试官:Kafka 如何优化内存缓冲机制造成的频繁 GC 问题?
  6. Spring mvc 参数半丁
  7. java7:核心技术与最佳实践读书笔记——类加载
  8. 偏移动画(TranslateTransform)
  9. 微信小程序wxs如何使用
  10. requests模块高级操作之cookie