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

题意

给定一个 \(n\) 个点边带权的无根树, 要求切断其中恰好 \(k\) 条边再连 \(k\) 条边权为 \(0\) 的边重新连成一棵树, 最大化新树上某条路径的权值和.

\(0\le k<n\le 3\times 10^5\). 边权的绝对值不超过 \(1\times 10^6\).

提示: 题目并不难

题解

当时场上做这题的时候根本不知道有wqs二分这种高端套路...看到提示之后果断跑路了qaq...

首先切断 \(k\) 条边再连 \(k\) 条 \(0\) 权边并最大化一条路径的权值和显然相当于最大化在树上选 \(k+1\) 条点不相交路径的权值和.

这种恰好选若干条的一般考虑wqs二分. 二分一个附加权值, 每次多选一条链就会多产生一些权值, 然后DP的时候就可以变成 "在树中选若干条链并最大化权值和". 定义 \(dp_{i,0/1/2}\). 为以 \(i\) 为根的子树中, \(i\) 号点度数为 \(0/1/2\) 时的最大权值. 注意单点也可以作为一条合法的链, 我们可以看成一条自环贡献两个度数.

那么分几种情况讨论就好了. 度数小的状态可以通过向子树连一条边的转移到度数大的状态. 注意其中链的数量的增减就好了.

以及wqs二分在DP的时候需要顺便计数, 计数部分用结构体来写会好写很多(而且好像跑得还更快)

还有就是注意在值相等的时候对于链的数量的选择要有侧重. 一般倾向于统一选多的, 然后在二分循环里具体问题具体分析.

参考代码

  1. #include <bits/stdc++.h>
  2. const int MAXV=3e5+10;
  3. const int MAXE=1e6+10;
  4. typedef long long intEx;
  5. const intEx INF=1e15;
  6. struct Edge{
  7. int from;
  8. int to;
  9. int dis;
  10. Edge* next;
  11. };
  12. Edge E[MAXE];
  13. Edge* head[MAXV];
  14. Edge* top=E;
  15. struct Data{
  16. intEx sum;
  17. int cnt;
  18. Data(){}
  19. Data(const intEx& s,int c):sum(s),cnt(c){}
  20. Data friend operator+(const Data& a,const Data& b){
  21. return Data(a.sum+b.sum,a.cnt+b.cnt);
  22. }
  23. Data friend operator-(const Data& a,const Data& b){
  24. return Data(a.sum-b.sum,a.cnt-b.cnt);
  25. }
  26. bool friend operator<(const Data& a,const Data& b){
  27. return a.sum==b.sum?a.cnt<b.cnt:a.sum<b.sum;
  28. }
  29. };
  30. int n;
  31. int k;
  32. Data add;
  33. Data dp[MAXV][3];
  34. void DFS(int,int);
  35. void Insert(int,int,int);
  36. int main(){
  37. scanf("%d%d",&n,&k);
  38. for(int i=1;i<n;i++){
  39. int a,b,c;
  40. scanf("%d%d%d",&a,&b,&c);
  41. Insert(a,b,c);
  42. Insert(b,a,c);
  43. }
  44. add.cnt=1;
  45. intEx l=-1e12,r=1e12;
  46. while(r-l>1){
  47. intEx mid=(l+r+1)>>1;
  48. add.sum=mid;
  49. DFS(1,0);
  50. Data cur=std::max(dp[1][0],std::max(dp[1][1],dp[1][2]));
  51. if(cur.cnt>=k+1)
  52. r=mid;
  53. else
  54. l=mid;
  55. }
  56. add.sum=r;
  57. DFS(1,0);
  58. Data cur=std::max(dp[1][0],std::max(dp[1][1],dp[1][2]));
  59. printf("%lld\n",cur.sum-(k+1)*r);
  60. return 0;
  61. }
  62. void DFS(int root,int prt){
  63. dp[root][0]=Data(0,0);
  64. dp[root][1]=Data(-INF,0);
  65. dp[root][2]=add;
  66. for(Edge* i=head[root];i!=NULL;i=i->next){
  67. if(i->to!=prt){
  68. DFS(i->to,root);
  69. Data mx=std::max(dp[i->to][0],std::max(dp[i->to][1],dp[i->to][2]));
  70. dp[root][2]=std::max(dp[root][2]+mx,dp[root][1]+Data(i->dis,0)+std::max(dp[i->to][0],dp[i->to][1]-add));
  71. Data tmp=dp[root][0]+Data(i->dis,0)+std::max(dp[i->to][0]+add,dp[i->to][1]);
  72. dp[root][1]=std::max(dp[root][1]+mx,tmp);
  73. dp[root][0]=dp[root][0]+mx;
  74. }
  75. }
  76. }
  77. inline void Insert(int from,int to,int dis){
  78. top->from=from;
  79. top->to=to;
  80. top->dis=dis;
  81. top->next=head[from];
  82. head[from]=top++;
  83. }

[BZOJ 5252][LOJ 2478][九省联考2018] 林克卡特树的更多相关文章

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

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

  2. luogu P4383 [九省联考2018]林克卡特树lct

    传送门 题目操作有点奇怪,不过可以发现这就是把树先变成\(k+1\)个连通块,然后每个连通块选一条路径(本题中一个点也是一条路径),然后依次接起来.所以实际上要求的是选出\(k+1\)条点不相交的路径 ...

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. [uva] 1671 History of Languages

    题目描述 输入两个DFA,判断是否等价. https://uva.onlinejudge.org/external/16/1671.pdf 输入 第一行T 可以接受的字母表 第二行N 状态数 接下去N ...

  2. For update带来的思考

    For update or not 起源 ​ 之所以想写这个专题,是因为最近在做一个抢占任务的实现.假设数据库很多个任务,在抢占发生之前任务的状态都是FREE.现在假设同时有一堆抢占线程开始工作,抢占 ...

  3. 产环境部署node记录(三): centOS 7 mySQL和mongoDB的安装

    [mySQL的安装]: CentOS7默认数据库是mariadb,现在来安装mySQL 1.下载安装包 这里下载了四个安装包,后面会用到 yum -y install perl perl-devel ...

  4. 生产环境部署node记录(二):pm2和nginx

    安装完node和npm ,接下来安装pm2 首先简单介绍下pm2,官网的介绍是: pm2 是一个带有负载均衡功能的Node应用的进程管理器.当你要把你的独立代码利用全部的服务器上的所有CPU,并保证进 ...

  5. ADO----nDSN

    //////////////链接数据库 非DSN模式/////////////////////////////    //CString strOpen="DSN=DBAddressBook ...

  6. automapper 自动映射 集成asp.net Core2.1

    学习博文:https://www.cnblogs.com/yan7/p/8085410.html 1.使用nuget 安装 <PackageReference Include="Aut ...

  7. Myeclipse安装与破解

    安装包+破解包 链接:https://pan.baidu.com/s/1G4mYsTOMDixyr2UmdqqY5A 提取码:a2n8 红色框框内的是安装包,蓝色框框内的是破解包 安装过程中比较简单, ...

  8. mysql安装配置、主从复制配置详解

    作者:NiceCui 本文谢绝转载,如需转载需征得作者本人同意,谢谢. 本文链接:http://www.cnblogs.com/NiceCui/p/8213723.html 邮箱:moyi@moyib ...

  9. Django HTML 转义

    HTML转义 模板对上下文传递的字符串进行输出时,会对以下字符自动转义 小于号< 转换为< 大于号> 转换为> 单引号' 转换为' 双引号" 转换为 " 与 ...

  10. Mac下 KGDB连接Linux

    kgdb按照资料说可以使用网络(kgdboe)和串口连接(kgdboc)等方式连接. 这里使用后者,资料比较多,下面是自己在Mac上进行配置连接的过程. 先说一下环境: 主机:Mac OSX 10.1 ...