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

一看这种题就不是lct。。。

除了直径好拿分,别的都难做。

所以必须转化

突破口在于:连“0”边

对于k=0,我们求直径

k=1,对于(p,q)一定是从p出发,走一段原树,走0(或不走),再走一段原树,所以要最大化原树的值的和。

选择最大两条 点不相交的链(注意:可以选择一个点,这时候链长为0)。然后一定可以首尾连起来得到答案

k更大的时候,选择最大的k+1条两两不相交的路径,然后一定存在方案使之连接起来,一定是最优解。(因为如果实际上最优解不用走k条0边,一定会把这些0边随便连一连废掉,对应选择一个点作为链)

所以,求最大的k+1条两两点不相交的路径。

点不相交,每次贪心取直径然后取反其实不好做。而且显然扩展性太差

树形DP

f[x][0/1/2][k]表示x为根的子树,从下面连接到x的度数是0/1/2,用k条链的最优解。特别地,从x开始往上的链归入f[x][1][*]。

转移时候枚举和当前儿子怎么连就好了。

看上去已经不能优化了。

然鹅

可以发现,如果f[x]函数表示选择x个链的最大总和

这是一个上凸函数!

就可以WQS二分了

具体地,每个链的额外花费mid的代价

然后求全局的最高点。没了k的限制就好做了

f[x][0/1/2]

(PS:

1.这个题如果连接的新边不是0应该也可以,但是必须是正数,负数的话转化就不对了,不一定走K次新边最优

2.如果k是一个区间也许也可以?

代码:

  1. #include<bits/stdc++.h>
  2. #define reg register int
  3. #define il inline
  4. #define numb (ch^'0')
  5. using namespace std;
  6. typedef long long ll;
  7. il void rd(int &x){
  8. char ch;x=;bool fl=false;
  9. while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
  10. for(x=numb;isdigit(ch=getchar());x=x*+numb);
  11. (fl==true)&&(x=-x);
  12. }
  13. namespace Miracle{
  14. const int N=3e5+;
  15. const ll inf=0x3f3f3f3f3f3f3f3f;
  16. int n,k;
  17. int b[N][];
  18. struct node{
  19. int nxt,to;
  20. ll val;
  21. }e[*N];
  22. int hd[N],cnt;
  23. void add(int x,int y,ll z){
  24. e[++cnt].nxt=hd[x];
  25. e[cnt].val=z;
  26. e[cnt].to=y;
  27. hd[x]=cnt;
  28. }
  29. struct dp{
  30. ll v;
  31. int c;
  32. dp(){}
  33. dp(ll a,int b){
  34. v=a;c=b;
  35. }
  36. dp operator +(const dp &b){
  37. return dp(v+b.v,c+b.c);
  38. }
  39. bool friend operator <(dp a,dp b){
  40. return (a.v<b.v||(a.v==b.v&&a.c<b.c));
  41. }
  42. void clear(){
  43. v=-inf;c=-0x3f3f3f3f;
  44. }
  45. }f[N][];
  46. ll sum;
  47. void dfs(int x,int fa,ll mid){
  48. f[x][].clear();
  49. f[x][].clear();
  50. f[x][].v=,f[x][].c=;
  51. for(reg i=hd[x];i;i=e[i].nxt){
  52. int y=e[i].to;
  53. if(y==fa) continue;
  54. dfs(y,x,mid);
  55. f[x][]=max(f[x][]+f[y][],f[x][]+f[y][]+dp(e[i].val+mid,-));
  56. f[x][]=max(f[x][]+f[y][],f[x][]+f[y][]+dp(e[i].val,));
  57. f[x][]=f[x][]+f[y][];
  58. }
  59. f[x][]=max(f[x][],f[x][]+dp(-mid,));
  60. f[x][]=max(f[x][],max(f[x][],f[x][]));
  61. }
  62. int check(ll mid){
  63. memset(hd,,sizeof hd);cnt=;
  64. sum=;
  65. for(reg i=;i<n;++i){
  66. add(b[i][],b[i][],b[i][]);
  67. add(b[i][],b[i][],b[i][]);
  68. }
  69. dfs(,,mid);
  70. // for(reg i=1;i<=n;++i){
  71. // cout<<" i "<<i<<" : "<<f[i][0].v<<" "<<f[i][0].c<<endl;
  72. // }
  73. sum=f[][].v;
  74. // cout<<" mid "<<mid<<" :: "<<sum<<" "<<f[1][0].c<<endl;
  75. return f[][].c;
  76. }
  77. int main(){
  78. rd(n);rd(k);
  79. ++k;
  80. ll l=,r=;
  81. for(reg i=;i<n;++i){
  82. rd(b[i][]);rd(b[i][]);rd(b[i][]);
  83. r+=abs(b[i][]);
  84. }l=-r;
  85. ll ans=-;
  86. while(l<=r){
  87. ll mid=(l+r)/;
  88. if(check(mid)>=k) ans=mid,l=mid+;
  89. else r=mid-;
  90. }
  91. int haha=check(ans);
  92. printf("%lld\n",sum+(ll)k*ans);
  93. return ;
  94. }
  95.  
  96. }
  97. signed main(){
  98. Miracle::main();
  99. return ;
  100. }
  101.  
  102. /*
  103. Author: *Miracle*
  104. Date: 2019/2/20 15:23:18
  105. */

总结:

1.转化为k+1个链

2.树形dp(经典问题)

3.凸函数,WQS二分

[八省联考2018]林克卡特树lct——WQS二分的更多相关文章

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

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

  2. 洛谷P4383 [八省联考2018]林克卡特树lct(DP凸优化/wqs二分)

    题目描述 小L 最近沉迷于塞尔达传说:荒野之息(The Legend of Zelda: Breath of The Wild)无法自拔,他尤其喜欢游戏中的迷你挑战. 游戏中有一个叫做“LCT” 的挑 ...

  3. [九省联考2018]林克卡特树(DP+wqs二分)

    对于k=0和k=1的点,可以直接求树的直径. 然后对于60分,有一个重要的转化:就是求在树中找出k+1条点不相交的链后的最大连续边权和. 这个DP就好.$O(nk^2)$ 然后我们完全不可以想到,将b ...

  4. 洛谷.4383.[八省联考2018]林克卡特树lct(树形DP 带权二分)

    题目链接 \(Description\) 给定一棵边带权的树.求删掉K条边.再连上K条权为0的边后,新树的最大直径. \(n,K\leq3\times10^5\). \(Solution\) 题目可以 ...

  5. P4383 [八省联考2018]林克卡特树lct 树形DP+凸优化/带权二分

    $ \color{#0066ff}{ 题目描述 }$ 小L 最近沉迷于塞尔达传说:荒野之息(The Legend of Zelda: Breath of The Wild)无法自拔,他尤其喜欢游戏中的 ...

  6. luogu4383 [八省联考2018]林克卡特树(带权二分+dp)

    link 题目大意:给定你 n 个点的一棵树 (边有边权,边权有正负) 你需要移除 k 条边,并连接 k 条权值为 0 的边,使得连接之后树的直径最大 题解: 根据 [POI2015]MOD 那道题, ...

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

    题解: zhcs的那个题基本上就是抄这个题的,不过背包的分数变成了70分.. 不过得分开来写..因为两个数组不能同时满足 背包的话就是 $f[i][j][0/1]$表示考虑i子树,取j条链,能不能向上 ...

  8. 洛谷 4383 [八省联考2018]林克卡特树lct——树形DP+带权二分

    题目:https://www.luogu.org/problemnew/show/P4383 关于带权二分:https://www.cnblogs.com/flashhu/p/9480669.html ...

  9. [BZOJ5252][八省联考2018]林克卡特树lct

    bzoj(上面可以下数据) luogu description 在树上选出\(k\)条点不相交的链,求最大权值. 一个点也算是一条退化的链,其权值为\(0\). sol 别问我为什么现在才写这题 首先 ...

随机推荐

  1. 利用备份技术获取apk本地存储数据

    即使设备没有root,我们也可以通过物理访问设备来获取应用程序的数据,我们还可以通过此方法改变一个应用程序的数据.如果一个应用程序将数据存储在客户端, 使用简单的密码或pin检查,攻击者有可能使用这种 ...

  2. 一条insert语句插入数据库

    CREATE TABLE test_main ( id INT NOT NULL, value VARCHAR(10), PRIMARY KEY(id) ); oracle插入方式:INSERT IN ...

  3. Java通过pinyin4j实现汉字转拼音

       碰到个需求,需要按用户名字的首字母来排序.这就需要获取汉字对应的拼音了,突然就想起了pinyin4j这个jar包,于是就开始写了个汉字转拼音的工具类.在此记录一下,方便后续查阅 一.Pom依赖 ...

  4. 微信小程序云开发之云函数创建

    云函数 云函数是一段运行在云端的代码,无需管理服务器,在开发工具内编写.一键上传部署即可运行后端代码. 小程序内提供了专门用于云函数调用的 API.开发者可以在云函数内使用 wx-server-sdk ...

  5. ElasticSearch查询 第一篇:搜索API

    <ElasticSearch查询>目录导航: ElasticSearch查询 第一篇:搜索API ElasticSearch查询 第二篇:文档更新 ElasticSearch查询 第三篇: ...

  6. C# 基于泛型的自定义线性节点链表集合示例

    本例子实现了如何自定义线性节点集合,具体代码如下: using System; using System.Collections; using System.Collections.Generic; ...

  7. 数位DP模板详解

    // pos = 当前处理的位置(一般从高位到低位) // pre = 上一个位的数字(更高的那一位) // status = 要达到的状态,如果为1则可以认为找到了答案,到时候用来返回, // 给计 ...

  8. 一个web应用的诞生(3)--美化一下

    经过上一章的内容,其实就页面层来说已结可以很轻松的实现功能了,但是很明显美观上还有很大的欠缺,现在有一些很好的前端css框架,如AmazeUI,腾讯的WeUI等等,这里推荐一个和flask集成很好的b ...

  9. 统计学习方法c++实现之六 支持向量机(SVM)及SMO算法

    前言 支持向量机(SVM)是一种很重要的机器学习分类算法,本身是一种线性分类算法,但是由于加入了核技巧,使得SVM也可以进行非线性数据的分类:SVM本来是一种二分类分类器,但是可以扩展到多分类,本篇不 ...

  10. WebShell代码分析溯源(第1题)墨者学院

    一.访问链接 二.下载系统源码后直接放到D盾里扫描,扫到后门文件 三.查看该木马文件 <?php error_reporting(0); $_GET['POST']($_POST['GET']) ...