[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的时候需要顺便计数, 计数部分用结构体来写会好写很多(而且好像跑得还更快)

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

参考代码

#include <bits/stdc++.h>

const int MAXV=3e5+10;
const int MAXE=1e6+10;
typedef long long intEx;
const intEx INF=1e15; struct Edge{
int from;
int to;
int dis;
Edge* next;
};
Edge E[MAXE];
Edge* head[MAXV];
Edge* top=E; struct Data{
intEx sum;
int cnt;
Data(){}
Data(const intEx& s,int c):sum(s),cnt(c){}
Data friend operator+(const Data& a,const Data& b){
return Data(a.sum+b.sum,a.cnt+b.cnt);
}
Data friend operator-(const Data& a,const Data& b){
return Data(a.sum-b.sum,a.cnt-b.cnt);
}
bool friend operator<(const Data& a,const Data& b){
return a.sum==b.sum?a.cnt<b.cnt:a.sum<b.sum;
}
}; int n;
int k;
Data add;
Data dp[MAXV][3]; void DFS(int,int);
void Insert(int,int,int); int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<n;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
Insert(a,b,c);
Insert(b,a,c);
}
add.cnt=1;
intEx l=-1e12,r=1e12;
while(r-l>1){
intEx mid=(l+r+1)>>1;
add.sum=mid;
DFS(1,0);
Data cur=std::max(dp[1][0],std::max(dp[1][1],dp[1][2]));
if(cur.cnt>=k+1)
r=mid;
else
l=mid;
}
add.sum=r;
DFS(1,0);
Data cur=std::max(dp[1][0],std::max(dp[1][1],dp[1][2]));
printf("%lld\n",cur.sum-(k+1)*r);
return 0;
} void DFS(int root,int prt){
dp[root][0]=Data(0,0);
dp[root][1]=Data(-INF,0);
dp[root][2]=add;
for(Edge* i=head[root];i!=NULL;i=i->next){
if(i->to!=prt){
DFS(i->to,root);
Data mx=std::max(dp[i->to][0],std::max(dp[i->to][1],dp[i->to][2]));
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));
Data tmp=dp[root][0]+Data(i->dis,0)+std::max(dp[i->to][0]+add,dp[i->to][1]);
dp[root][1]=std::max(dp[root][1]+mx,tmp);
dp[root][0]=dp[root][0]+mx;
}
}
} inline void Insert(int from,int to,int dis){
top->from=from;
top->to=to;
top->dis=dis;
top->next=head[from];
head[from]=top++;
}

[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. 一张图解决Struts2添加源码

    主要是选择的路径:F:/struts2/struts-2.3.31/src/core/src/main/java

  2. C#开发一应用的总结

    要搭建测试环境. Webbrowser使用方面: 重新加载一页面后,要获取新的内容要使用重新使用browser.Document获取: HtmlElement的GetElementsByTagName ...

  3. [javaSE] 网络编程(概述)

    网络通信的步骤, 1.找到对方的ip 2.数据发送到对方指定的应用程序上,为了标识这些应用程序,用数字进行标识,这个数字就是端口 3.定义通信规则,这个规则就称为协议 国际组织定义了通用协议 TCP/ ...

  4. python可视化基础

    常用的python可视化工具包是matplotlib,seaborn是在matplotlib基础上做的进一步封装.入坑python可视化,对有些人来说如同望山跑死马,心气上早输了一节.其实学习一门新知 ...

  5. Q:链表的倒数第K个元素

    问题:如何得到链表中的倒数第k个元素?   一种简单的思路是遍历链表一遍,并统计出链表中节点的数目,然后计算出倒数第k个元素到链表头节点的元素的距离,然后得到对应的结果.但是,我们能否有一种更加简便的 ...

  6. javascript元素跟随鼠标在指定区域运动

    元素跟随鼠标在指定区域运动通常是用在商城图片的放大镜中,下面是完整的Demo: <!DOCTYPE html> <html lang="en"> <h ...

  7. 51Nod1053 最大M子段和V2 二分+DP

    传送门 直接DP的话最多也只能做到\(O(nm)\),对于\(5\times 10^4\)的数据范围实在无能为力 夹克老爷提供的做法是贪心,思想大概是在调整的同时,合理构造每个选择对应的新状态,使得新 ...

  8. html-使用表单标签实现注册页面

    案例说明: - 使用表格实现页面效果 - 超链接不想要有效果,使用href="#" - 如果表格里面的单元格没有内容,使用空格作为占位符   - 使用图片标签提交表单 <in ...

  9. IIS 部署 Python Django网站流程(受够了野路子)

    知道的,百度上搜出来的东西质量令人唏嘘.当你求助的时候多半还得靠自己,或者靠Google 介入正题,详细来一遍流程吧 当然,我是用Visual Studio 2019 来编辑开发Django项目的,如 ...

  10. Java 实验案例(类和对象篇)

    实验任务 任务一:手机类的封装 任务二:基于控制台的购书系统 任务三:简单的投票程序 实验内容 任务一:手机类的封装 任务目的 理解和掌握面向对象的设计过程 掌握类的结构和定义过程 掌握构造方法及其重 ...