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

https://www.luogu.org/problemnew/show/P4383

分析:

  • 题意等价于选择\(K\)条点不相交的链,使得总路径长度和最大。
  • 设\(f[x][i][0/1/2]\)表示\(x\)子树中选了\(i\)个,\(x\)的当前度数为\(0/1/2\)的答案。
  • 然后我们感性理解一下可知,选\(k\)个点的方案,一定能够从\(k-1\)个点的方案中转移过来的,不会出现从\(k-i(i>1)\)上再选若干个不在\(k-1\)的方案中的链转移过来答案更优。
  • 那么由于我们选择的链的权值是不断变小的,可知\(dp\)值是个凸函数,且单峰。
  • 使用带权二分即可,对于本题,整数二分就可以通过。

代码:

  1. // luogu-judger-enable-o2
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5. using namespace std;
  6. #define N 300050
  7. typedef long long ll;
  8. const ll inf = 1ll<<60;
  9. int head[N],to[N<<1],nxt[N<<1],cnt,val[N<<1],n,K,siz[N];
  10. // ll f[N][105][3],tmp[105][3];
  11. struct A {
  12. ll x; int k;
  13. A() {}
  14. A(ll x_,int k_) {x=x_, k=k_;}
  15. bool operator < (const A &u) const {
  16. return x==u.x ? k>u.k : x<u.x;
  17. }
  18. A operator + (const A &u) const {
  19. return A(x+u.x, k+u.k);
  20. }
  21. }f[N][3],ans,tmp[3];
  22. inline void add(int u,int v,int w) {
  23. to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; val[cnt]=w;
  24. }
  25. template<typename T>void chkmax(T &x,T y) {if(x<y)x=y;}
  26. template<typename T>void chkmin(T &x,T y) {if(y<x)x=y;}
  27. ll C;
  28. // void dfs(int x,int y) {
  29. // int i,j,k,p,q; siz[x]=1;
  30. // memset(f[x],0xc0,sizeof(f[x]));
  31. // f[x][0][0]=f[x][1][2]=0;
  32. // for(i=head[x];i;i=nxt[i]) if(to[i]!=y) {
  33. // dfs(to[i],x);
  34. // for(j=0;j<=K&&j<=siz[x];j++) for(k=0;k<3;k++) tmp[j][k]=f[x][j][k], f[x][j][k]=-inf;
  35. // int t=to[i],len=val[i];
  36. // for(j=0;j<=K&&j<=siz[x];j++) {
  37. // for(k=0;k<=K-j+1&&k<=siz[to[i]];k++) {
  38. // //not choose
  39. // for(p=0;p<3;p++) for(q=0;q<3;q++) chkmax(f[x][j+k][p],tmp[j][p]+f[t][k][q]);
  40. // //choose
  41. // chkmax(f[x][j+k+1][1],tmp[j][0]+f[t][k][0]+len);
  42. // chkmax(f[x][j+k][1],tmp[j][0]+f[t][k][1]+len);
  43. // chkmax(f[x][j+k][2],tmp[j][1]+f[t][k][0]+len);
  44. // chkmax(f[x][j+k-1][2],tmp[j][1]+f[t][k][1]+len);
  45. // }
  46. // }
  47. // siz[x]+=siz[to[i]];
  48. // }
  49. // }
  50. void dfs(int x,int y) {
  51. int i,p,q;
  52. f[x][0]=A(0,0); f[x][1]=A(-inf,0); f[x][2]=A(C,1);
  53. for(i=head[x];i;i=nxt[i]) if(to[i]!=y) {
  54. int t=to[i];
  55. dfs(to[i],x);
  56. memcpy(tmp,f[x],sizeof(f[x]));
  57. f[x][0]=f[x][1]=f[x][2]=A(-inf,0);
  58. //not choose
  59. for(p=0;p<3;p++) for(q=0;q<3;q++) chkmax(f[x][p],tmp[p]+f[t][q]);
  60. chkmax(f[x][1],tmp[0]+f[t][0]+A(val[i]+C,1));
  61. chkmax(f[x][1],tmp[0]+f[t][1]+A(val[i],0));
  62. chkmax(f[x][2],tmp[1]+f[t][0]+A(val[i],0));
  63. chkmax(f[x][2],tmp[1]+f[t][1]+A(val[i]-C,-1));
  64. }
  65. }
  66. int main() {
  67. scanf("%d%d",&n,&K);
  68. K++;
  69. int i,x,y,z;
  70. for(i=1;i<n;i++) {
  71. scanf("%d%d%d",&x,&y,&z);
  72. add(x,y,z); add(y,x,z);
  73. }
  74. // dfs(1,0);
  75. // printf("%lld\n",max(max(f[1][K][0],f[1][K][1]),f[1][K][2]));
  76. ll l=-1e9, r=1e9;
  77. while(l<r) {
  78. ll mid=(l+r)>>1;
  79. C=mid; dfs(1,0);
  80. ans=max(max(f[1][0],f[1][1]),f[1][2]);
  81. if(ans.k>K) r=mid;
  82. else if(ans.k==K) {
  83. printf("%lld\n",ans.x-K*C); return 0;
  84. }
  85. else l=mid+1;
  86. }
  87. l--;
  88. C=l; dfs(1,0);
  89. ans=max(max(f[1][0],f[1][1]),f[1][2]);
  90. printf("%lld\n",ans.x-K*C);
  91. }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    题目链接 题意分析 一句话题意就是 : 让你选出\((k+1)\)条不相交的链 使得这些链的边权总和最大 (这些链可以是点) 我们考虑使用树形\(DP\) \(dp[i][j][0/1/2]\)表示以 ...

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

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

随机推荐

  1. 【JavaScript】BOM和DOM

    在第一篇JavaScript视频总结博客中.是对JavaScript做了一个宏观的认识.当中,不知道大家可否还记得.JavaScript的核心部分包含哪些? JavaScript的核心部分主要包含三个 ...

  2. Android平台录音音量计的实现

    今天博主要给大家分享的是怎样在Android平台上实现录音时的音量指示计.开门见山.先来看一张Demo的效果图: 如上图所看到的,两个button各自是開始录音和停止录音,中间的两个数字前后分别代表音 ...

  3. 【BZOJ3309】DZY Loves Math 莫比乌斯反演+线性筛(好题)

    [BZOJ3309]DZY Loves Math Description 对于正整数n,定义f(n)为n所含质因子的最大幂指数.例如f(1960)=f(2^3 * 5^1 * 7^2)=3, f(10 ...

  4. Delphi的未来,一点浅见

    我是新手评议谈不上,但个人认为必须得跟主流大佬走,这同时也得有自己的核心技术,才最终能让自己成为大佬. ------------------------------------------------ ...

  5. IOS navigationItem 设置返回button,title图片和rightBarButtonItem

    1.自己定义返回button UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:@"返回" st ...

  6. Swift学习 --- 2.1基础部分

    1.swift 能够省去; 2.println与print的差别就是一个能够换行一个不能够 3.swift省去了.h与.m 直接一个swift文件 4.元组能够返回多个值,元组(tuples)把多个值 ...

  7. 变量动态选取资源ID

    1.使用Resources 类的 getIdentifier方法  Resources res=getResources();        return res.getIdentifier(type ...

  8. 上传项目至GitHub

      在windows系统客户端安装git工具. 注:如何安装git工具在此不做介绍,如需了解可网上搜索安装介绍.   在“本地文件”中添加“.git文件”,用于git管理. 进入本地文件夹,右击鼠标- ...

  9. 每天一个Linux命令(30)ln命令

    ln命令用来为文件创建链接,连接类型分为硬链接和符号链接两种,默认的连接类型是硬连接.如果要创建符号连接必须使用"-s"选项.   (1)用法: 用法:  ln  [options ...

  10. Data Structure Binary Tree: Print ancestors of a given binary tree node without recursion

    http://www.geeksforgeeks.org/print-ancestors-of-a-given-binary-tree-node-without-recursion/ #include ...