思路

可以考虑另一种想法:因为我们发现,答案是肯定不会大于在原来的树上的最短路径的。所以原来的最短路是(有可能的)最大值!

我们把树变成这样,提取出1~n的路径,方便观看撕烤:

(它有个我起的名字,叫灯笼树态,处理树上路径与其余部分之间的关系时画图用,并非真实的数据结构)

我们称被提取出来的树上路径(本题为1~n)为灯笼线,路径上每一个节点及其下悬挂的子树称为灯笼子树,每一个灯笼子树的根节点叫悬挂点

显然,悬挂点一定在灯笼线上。任意一个点的悬挂点就是它所在的灯笼子树的悬挂点。一个点如果在灯笼线上,那么它的悬挂点是自己。

那么什么时候原来的最短路不是答案呢?

那么就是对于任何的u和v,将它们连接起来后,新的最短路都比原来的最短路小。

换句话说:设灯笼线上的两个点x和y分别为准备新加边的u,v的悬挂点。那么只需比较(x到y的路径长度)和(ux,vy的长度和再加上每次询问时的那个值)即可。

(重头戏来了!)

如果上文的u和v再同一颗灯笼子树内呢?

(*)于是,你发现一个结论:如果一颗灯笼子树除悬挂点外有超过两个以上的节点,那么连接这颗灯笼子树内的两个没有直接边相连的点,无论询问多少,Ans会取到原图的最短路,也就是理论最大值。

所以,我们仅需考虑每颗颗灯笼子树除悬挂点外仅有1的点的原树即可。

由于要比较(x到y的路径长度)和(ux,vy的长度和再加上每次询问时的那个值),所以我们可以算出最大的(x到y的路径长度)-(ux,vy的长度和),每次询问将其加上询问值并与0比较即可。

如何算出(x到y的路径长度)-(ux,vy的长度和)?将这个式子拆开分别维护,一遍dfs,用heap维护一下。建议读者自行撕烤这部分内容。

Code:

#include <cstdio>
#include <queue>
using namespace std;
const int S=600006;
struct info
{
int x;
long long s;
inline bool operator<(const info &a) const
{
return s<a.s;
}
}st[S];
priority_queue<info> pq;
int n,m,h[S],nx[S],v[S],w[S],eg=1,s[S],fa[S],top,lc[S],rc[S];
const long long infl=(1ll<<60)-1;
long long dep[S],res=-infl;
bool flag,mk[S];
void read(int &s)
{
s=0;char c=getchar();
while (c<'0' || c>'9') c=getchar();
while (c>='0' && c<='9') s=(s<<1)+(s<<3)+(c^48),c=getchar();
}
inline void egadd(int uu,int vv,int ww)
{
nx[++eg]=h[uu];h[uu]=eg;
v[eg]=vv;w[eg]=ww;
}
void dfs_1(int x)
{
s[x]=1;
for (int i=h[x];i;i=nx[i])
if (v[i]!=fa[x])
{
fa[v[i]]=x;
dep[v[i]]=dep[x]+w[i];
dfs_1(v[i]);
s[x]+=s[v[i]];
}
}
bool check()
{
int o=n;
if (s[o]>2) return false;
while (o!=1)
{
if (s[fa[o]]-s[o]>2) return false;
mk[o]=true;
o=fa[o];
}
mk[1]=true;
return true;
}
inline long long ma(long long a,long long b){return a>b?a:b;}
inline long long mi(long long a,long long b){return a<b?a:b;}
void dfs_3(int x)//这里是将原树转为二叉树,因为灯笼子树大小不超过两个点的树就是一颗二叉树
{
for (int i=h[x];i;i=nx[i])
if (v[i]!=fa[x])
{
dfs_3(v[i]);
if (mk[v[i]])
{
lc[x]=v[i];
break;
}
}
for (int i=h[x];i;i=nx[i])
if (v[i]!=fa[x])
if (!mk[v[i]])
{
rc[x]=v[i];
break;
}
}
void dfs_2(int x)
{
if (lc[x]) dfs_2(lc[x]);
if (rc[x]) dfs_2(rc[x]);
while (!pq.empty() && fa[pq.top().x]==x)
st[++top]=pq.top(),pq.pop();
if (!pq.empty()) res=ma(res,pq.top().s+dep[x]);
while (top) pq.push(st[top--]);
pq.push((info){x,2*(mk[x]?0:dep[x]-dep[fa[x]])-dep[x]});
}
int main()
{
read(n);read(m);
for (int i=1;i<n;i++)
{
int uu,vv,ww;
read(uu);read(vv);read(ww);
egadd(uu,vv,ww);
egadd(vv,uu,ww);
}
dfs_1(1);
flag=check();
if (flag) dfs_3(1),dfs_2(1);
int x;
while (m--)
{
read(x);
if (flag) printf("%lld\n",dep[n]+mi(0,res+x));
else printf("%lld\n",dep[n]);
}
return 0;
}

CF1016F 【Road Projects】的更多相关文章

  1. 【26.83%】【Codeforces Round #380C】Road to Cinema

    time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...

  2. 【USACO 2017FEB】 Why Did the Cow Cross the Road III

    [题目链接] 点击打开链接 [算法] 树状数组 [代码] #include<bits/stdc++.h> using namespace std; #define MAXN 100010 ...

  3. 【USACO 2017Feb】 Why Did the Cow Cross the Road

    [题目链接] 点击打开链接 [算法] dist[i][j][k]表示当前走到(i,j),走的步数除以3的余数为k的最小花费 spfa即可 [代码] #include<bits/stdc++.h& ...

  4. 【POJ 3352】 Road Construction

    [题目链接] 点击打开链接 [算法] tarjan算法求边双联通分量 [代码] #include <algorithm> #include <bitset> #include ...

  5. 【Machine Learning】机器学习及其基础概念简介

    机器学习及其基础概念简介 作者:白宁超 2016年12月23日21:24:51 摘要:随着机器学习和深度学习的热潮,各种图书层出不穷.然而多数是基础理论知识介绍,缺乏实现的深入理解.本系列文章是作者结 ...

  6. 【微服务】SpringBoot、SpringCloud相关

    深入学习微框架:Spring Boot:   http://www.infoq.com/cn/articles/microframeworks1-spring-boot/ Spring Boot--2 ...

  7. 【Vegas原创】SVN的搭建及安装使用

    中文手册:http://tortoisesvn.net/docs/nightly/TortoiseSVN_zh_CN/index.html 所需程序: 1,TortoiseSVN  http://so ...

  8. 【BZOJ-3545&3551】Peaks&加强版 Kruskal重构树 + 主席树 + DFS序 + 倍增

    3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1202  Solved: 321[Submit][Sta ...

  9. 【C# -- OpenCV】Emgu CV 第一个实例

    原文 [C# -- OpenCV]Emgu CV 第一个实例 Emgu CV下载地址 http://sourceforge.net/projects/emgucv/files/ 找最新的下就行了,傻瓜 ...

随机推荐

  1. Vue学习笔记【32】——Vue路由(watch、computed和methods之间的对比)

    computed属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算.主要当作属性来使用: methods方法表示一个具体的操作,主要书写业务逻辑: watch一个对象,键是需要观察的表达式,值是 ...

  2. 【JS】js引擎执行过程

    概述 js引擎执行过程主要分为三个阶段,分别是语法分析,预编译和执行阶段,上篇文章我们介绍了语法分析和预编译阶段,那么我们先做个简单概括,如下: 语法分析: 分别对加载完成的代码块进行语法检验,语法正 ...

  3. 轻松解决U盘拷贝文件时提示文件过大问题

    现在的高科技时代生活中,u盘的使用已经是许多从事电脑it行业的人每天都必须要用到的用具.可以在一台电脑上使用u盘拷贝文件到另外一台电脑上进行使用,加上它的身材小巧,非常方便我们随身携带到任何地方进行使 ...

  4. Python基础教程(005)--为什么要学习Python?

    前言 为什么要选择Python学习 知识点 因为Python代码量少. 同样一个问题,用不同的语言,代码量差距还是很大的.一半情况下,Python是java的1比5,所以说,人生苦短,我用Python ...

  5. [CSP-S模拟测试]:E(贪心)

    题目传送门(内部题48) 输入格式 第一行一个整数$n$.接下来$n$行每行两个整数$x_i,y_i$. 输出格式 一行一个整数表示答案. 样例 样例输入$1$: 23 72 5 样例输出$1$: 样 ...

  6. winform DataGridView的虚模式填充,CellValueNeeded事件的触发条件

    虚模式填充常用来处理大量数据,某个字段的显示问题. DataGridView是.net 2.0新增的表格数据编辑和显示控件,简单的数据显示和编辑,只需直接和数据源绑定就可以了. 对于 一些特殊情况,我 ...

  7. centos安装virtualbox

    参考:http://www.if-not-true-then-false.com/2010/install-virtualbox-with-yum-on-fedora-centos-red-hat-r ...

  8. The Preliminary Contest for ICPC Asia Shanghai 2019 (B L )

    B. Light bulbs 思路:差分 + 离散化, 好不容易懂了差分却没想到离散化,还是要罗老板出马..... AC代码: #include<bits/stdc++.h> using ...

  9. 比较全面的CSS hack方式一览

    转载请注明来自CSDN freshlover的博客专栏<史上最全CSS Hack方式一览>   做前端多年,虽然不是经常需要hack,但是我们经常会遇到各浏览器表现不一致的情况.基于此,某 ...

  10. fedora 25重新安装引导

    引导区被其他系统给覆盖了,重新安装引导 grub2-install /dev/sdb GRUB_SAVEDEFAULT=true BIOS grub2-mkconfig -o /boot/grub2/ ...