题目大意:

  给一个n个节点的树,然后将其分成k+1个联通块,再在每个联通块取一条路径,将其连接起来,求连接起来的路径最大权值。

题解:

  考场只会20分,还都打挂了……

  60分的做法其实并不难,nk DP即可,设$f(i,j,0/1/2)$表示i子树选取了j个联通块,i这个节点连了0/1/2条边时的最优解。

  100分的做法就是60分做法的拓展。

  很容易想到一件事,就是以联通块数为x轴,最优解为y轴,那么这个图像应该是一个单峰上凸函数。同时该离散函数每相邻两点间的斜率是递减的:因为考虑当前联通块数为a,则当联通块数为a+1时,必然是在a时最优解上再连接一段新切出的可空路径并割去一部分可空路径,当补上一条新路径时,我们很容易知道这次补上的路径-割去路径一定小于以前做的同样操作(最优性)。

  这样我们发现斜率是具有单调性的(即单调减)。那么我们二分这个斜率,并将原图像减去这个斜率对应的正比例函数,会发现,新图像将会在这个斜率对应点的位置最高,同时也是一个斜率递减函数。

  那么我们考虑如何求出此时的答案:新图像上的最高点权值+新图像上最高点联通块数*斜率。

  我们考虑这个东西怎么求。

  设二元组$f(i,0/1/2)$表示i节点连了0/1/2条边时的最优解和其联通块数(尽量小)。特别的没有连边的i,算为一个联通块,2为0/1/2这三个状态的最优解。

  考虑这个东西怎么转移:

  假设已经得到子节点v的答案。

  对于$f(x,2)$,我们有三种选择,1.保持原来不变,把$f(v,2)$加上;2.由$f(x,1)$和$f(v,1)$合并;3.由$f(x,1)和f(v,0)$合并。

  $f(x,1)$,我们同样有三种选择,大体同上者。

  $f(x,0)$,我们只有一种选择,即和$f(v,2)$结合。

  我们以$f(x,2)$为例:对于第一种情况,联通块数不变直接合并即可,对于第二种情况联通块数减少1,第三种情况同样减少了1个联通块。

  得到结果以后比较k+1与最优解对应的联通块数,大于则说明斜率过小,否则说明斜率还可能更大。

代码:

 #include "bits/stdc++.h"

 using namespace std;

 inline int read(){
int s=,k=;char ch=getchar();
while (ch<''|ch>'') ch=='-'?k=-:,ch=getchar();
while (ch>&ch<='') s=s*+(ch^),ch=getchar();
return s*k;
} typedef long long ll; const int N=3e5+; struct edges{
int v,w;edges *last;
}edge[N<<],*head[N];int cnt; inline void push(int u,int v,int w) {
edge[++cnt]=(edges){v,w,head[u]},head[u]=edge+cnt;
} int n,k;
ll slope;
const ll inf=1e15; struct node {
ll val,num;
node(){val=num=;}
node(ll v,ll nm):val(v),num(nm){}
inline ll &operator [](int x){
return x?num:val;
}
inline void max(node a){
if(a[]>val||(a[]==val&&a[]<num))
(*this)=a;
}
inline void add(node a,node b){
if (a[]==-inf||a[]==-inf) return ;
a[]+=b[],a[]+=b[];
max(a);
}
inline void add(node a,node b,int w,int opt){
if(a[]==-inf||b[]==-inf) return ;
a[]+=b[]-opt,a[]+=b[]+w+slope*opt;
if(a[]<=) return ;
max(a);
}
inline node fa(){
return node(val-slope,num+);
}
}f[N][]; inline void dp(int x,int fa){
f[x][]=f[x][]=f[x][]=node();
f[x][][]=f[x][][]=-inf;
for (edges *i=head[x];i;i=i->last) if(i->v!=fa) {
dp(i->v,x);
f[x][].add(f[x][],f[i->v][]);
f[x][].add(f[x][],f[i->v][],i->w,);
f[x][].add(f[x][],f[i->v][],i->w,);
f[x][].add(f[x][],f[i->v][]);
f[x][].add(f[x][],f[i->v][],i->w,);
f[x][].add(f[x][],f[i->v][],i->w,-);
f[x][].add(f[x][],f[i->v][]);
}
f[x][].max(f[x][]);
f[x][].max(f[x][]);
f[x][].max(f[x][].fa());
} int main(){
n=read(),k=read()+;
for (int i=;i<n;++i) {
int a=read(),b=read(),w=read();
push(a,b,w),push(b,a,w);
}
ll l=-1e12,r=1e12;
node now;
ll ans=;
while (l<=r) {
slope=l+r>>;
dp(,);
now=f[][];
if(now[]<=k)
ans=now[]+slope*k,r=slope-;
else l=slope+;
}
printf("%lld\n",ans);
}

【HEOI 2018】Day2 T2 林克卡特树的更多相关文章

  1. [八省联考2018]林克卡特树lct——WQS二分

    [八省联考2018]林克卡特树lct 一看这种题就不是lct... 除了直径好拿分,别的都难做. 所以必须转化 突破口在于:连“0”边 对于k=0,我们求直径 k=1,对于(p,q)一定是从p出发,走 ...

  2. [BZOJ 5252][LOJ 2478][九省联考2018] 林克卡特树

    [BZOJ 5252][LOJ 2478][九省联考2018] 林克卡特树 题意 给定一个 \(n\) 个点边带权的无根树, 要求切断其中恰好 \(k\) 条边再连 \(k\) 条边权为 \(0\) ...

  3. LuoguP4383 [八省联考2018]林克卡特树lct

    LuoguP4383 [八省联考2018]林克卡特树lct https://www.luogu.org/problemnew/show/P4383 分析: 题意等价于选择\(K\)条点不相交的链,使得 ...

  4. luoguP4383 [八省联考2018]林克卡特树(树上dp,wqs二分)

    luoguP4383 [八省联考2018]林克卡特树(树上dp,wqs二分) Luogu 题解时间 $ k $ 条边权为 $ 0 $ 的边. 是的,边权为零. 转化成选正好 $ k+1 $ 条链. $ ...

  5. P4383 [八省联考2018]林克卡特树 树形dp Wqs二分

    LINK:林克卡特树 作为树形dp 这道题已经属于不容易的级别了. 套上了Wqs二分 (反而更简单了 大雾 容易想到还是对树进行联通情况的dp 然后最后结果总和为各个联通块内的直径. \(f_{i,j ...

  6. 【BZOJ5252】林克卡特树(动态规划,凸优化)

    [BZOJ5252]林克卡特树(动态规划,凸优化) 题面 BZOJ(交不了) 洛谷 题解 这个东西显然是随着断开的越来越多,收益增长速度渐渐放慢. 所以可以凸优化. 考虑一个和\(k\)相关的\(dp ...

  7. 【HEOI 2018】林克卡特树

    转载请注明出处:http://www.cnblogs.com/TSHugh/p/8776179.html 先说60分的.思路题解上很清晰: 问题似乎等价于选K+1条点不相交的链哎!F(x,k,0/1/ ...

  8. bzoj5252 [2018多省省队联测]林克卡特树

    斜率优化树形dp?? 我们先将问题转化成在树上选K+1条互不相交路径,使其权值和最大. 然后我们考虑60分的dp,直接维护每个点子树内选了几条路径,然后该点和0/1/2条路径相连 然后我们会发现最后的 ...

  9. BZOJ5252 八省联考2018林克卡特树(动态规划+wqs二分)

    假设已经linkcut完了树,答案显然是树的直径.那么考虑这条直径在原树中是怎样的.容易想到其是由原树中恰好k+1条点不相交的链(包括单个点)拼接而成的.因为这样的链显然可以通过linkcut拼接起来 ...

随机推荐

  1. sqlite 数据类型 <转>

    一般数据采用的固定的静态数据类型,而SQLite采用的是动态数据类型,会根据存入值自动判断.SQLite具有以下五种数据类型: 1.NULL:空值.2.INTEGER:带符号的整型,具体取决有存入数字 ...

  2. CoolBlog开发笔记第5课:请求与响应

    教程目录 1.1 CoolBlog开发笔记第1课:项目分析 1.2 CoolBlog开发笔记第2课:搭建开发环境 1.3 CoolBlog开发笔记第3课:创建Django应用 1.4 CoolBlog ...

  3. 不是标准execl转换处理方法

    不是标准execl的主要原因就是原本的html.xml.txt尾椎的文件,更改成了xls尾椎的文件 面对这种问题,最开始我用了jawin.jar,但是始终会报错,NoClassDefFoundErro ...

  4. Linux/Windows远程桌面

    WINDOWS远程连接LINUX配置(LINUX VNC Server配置):   1.查看本机是否有安装vnc(centOS5默认有安装vnc) rpm -q vnc vnc-server 如果显示 ...

  5. RPi:QT+wiringPi demo程序

    一个项目里面要用到这玩意儿,网上查了几篇文章凑出来最后还是不行,自己灵机一动就成了. 今天再次搜索的时候,发现另一篇文章已经讲明白了,真是欲哭无泪 程序大部分参考的是之前学qt的摸索出来的,其实只要在 ...

  6. PHP基础(一)--字符串函数大盘点(基础篇)

    参考地址http://php.net/manual/zh/ref.strings.php addcslashes - 以 C 语言风格使用反斜线转义字符串中的字符    string addcslas ...

  7. J2EE--常见面试题总结 -- (二)

    1 Spring拦截器的基本功能是什么? 拦截器是基于Java的反射机制的,是在面向切面编程的就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法比如动态代理就是拦截器的简单 ...

  8. 从输入一个URL到页面完全显示发生了什么?

    这是经典的前端问题,主要是对浏览器的工作原理有个理解! 网络通信走的一般是五层因特网协议,详见下图.图片来自于https://images2018.cnblogs.com/blog/882926/20 ...

  9. VueJs(12)---vue-router(导航守卫,路由元信息)

    vue-router(导航守卫,路由元信息) 之前泄露两篇有关vue-router博客: VueJs(10)---vue-router(进阶1) VueJs(11)---vue-router(进阶2) ...

  10. Java注解处理器--编译时处理的注解

    1. 一些基本概念 在开始之前,我们需要声明一件重要的事情是:我们不是在讨论在运行时通过反射机制运行处理的注解,而是在讨论在编译时处理的注解.注解处理器是 javac 自带的一个工具,用来在编译时期扫 ...