[BZOJ 5252][LOJ 2478][九省联考2018] 林克卡特树
[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] 林克卡特树的更多相关文章
- [九省联考2018]林克卡特树(DP+wqs二分)
对于k=0和k=1的点,可以直接求树的直径. 然后对于60分,有一个重要的转化:就是求在树中找出k+1条点不相交的链后的最大连续边权和. 这个DP就好.$O(nk^2)$ 然后我们完全不可以想到,将b ...
- luogu P4383 [九省联考2018]林克卡特树lct
传送门 题目操作有点奇怪,不过可以发现这就是把树先变成\(k+1\)个连通块,然后每个连通块选一条路径(本题中一个点也是一条路径),然后依次接起来.所以实际上要求的是选出\(k+1\)条点不相交的路径 ...
- [八省联考2018]林克卡特树lct——WQS二分
[八省联考2018]林克卡特树lct 一看这种题就不是lct... 除了直径好拿分,别的都难做. 所以必须转化 突破口在于:连“0”边 对于k=0,我们求直径 k=1,对于(p,q)一定是从p出发,走 ...
- LuoguP4383 [八省联考2018]林克卡特树lct
LuoguP4383 [八省联考2018]林克卡特树lct https://www.luogu.org/problemnew/show/P4383 分析: 题意等价于选择\(K\)条点不相交的链,使得 ...
- luoguP4383 [八省联考2018]林克卡特树(树上dp,wqs二分)
luoguP4383 [八省联考2018]林克卡特树(树上dp,wqs二分) Luogu 题解时间 $ k $ 条边权为 $ 0 $ 的边. 是的,边权为零. 转化成选正好 $ k+1 $ 条链. $ ...
- [BZOJ5252][八省联考2018]林克卡特树lct
bzoj(上面可以下数据) luogu description 在树上选出\(k\)条点不相交的链,求最大权值. 一个点也算是一条退化的链,其权值为\(0\). sol 别问我为什么现在才写这题 首先 ...
- 洛谷P4383 [八省联考2018]林克卡特树lct(DP凸优化/wqs二分)
题目描述 小L 最近沉迷于塞尔达传说:荒野之息(The Legend of Zelda: Breath of The Wild)无法自拔,他尤其喜欢游戏中的迷你挑战. 游戏中有一个叫做“LCT” 的挑 ...
- [八省联考2018]林克卡特树lct
题解: zhcs的那个题基本上就是抄这个题的,不过背包的分数变成了70分.. 不过得分开来写..因为两个数组不能同时满足 背包的话就是 $f[i][j][0/1]$表示考虑i子树,取j条链,能不能向上 ...
- BZOJ5252 八省联考2018林克卡特树(动态规划+wqs二分)
假设已经linkcut完了树,答案显然是树的直径.那么考虑这条直径在原树中是怎样的.容易想到其是由原树中恰好k+1条点不相交的链(包括单个点)拼接而成的.因为这样的链显然可以通过linkcut拼接起来 ...
随机推荐
- kafka 启动 报错cannot allocate memory,即内存不足
错误提示: Java Hotspot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x00000000c5330000, 9865134 ...
- POJ 1062 昂贵的聘礼(枚举限制条件——Dijkstra算法)
题目: 年轻的探险家来到了一个印第安部落里.在那里他和酋长的女儿相爱了,于是便向酋长去求亲.酋长要他用10000个金币作为聘礼才答应把女儿嫁给他.探险家拿不出这么多金币,便请求酋长降低要求.酋长说:& ...
- UIKit 框架之UITextView
// // ViewController.m // UItextView // // Created by City--Online on 15/5/22. // Copyright (c) 2015 ...
- [转]C#综合揭秘——Entity Framework 并发处理详解
本文转自:http://www.cnblogs.com/leslies2/archive/2012/07/30/2608784.html 引言 在软件开发过程中,并发控制是确保及时纠正由并发操作导致的 ...
- Sqlserver 还原
--完整还原 RESTORE DATABASE demoData FROM DISK=N'D:\Backup\demoData.bak'; RESTORE DATABASE { database_na ...
- T-sql 编程
---------------------------T-SQL编程--------------------------1.声明变量--declare @name nvarchar(50)--decl ...
- PHP module 安装
Part1:不重新安装php,安装zlib模块--------20171229 先安装zlib源码包 指定到目录 一台服务器,编译PHP时未设置参数,导致缺少zlib扩展,无法执行解压缩,错误信息是: ...
- GitHub fork的使用
我的GitHub账号是lanshanxiao,fork的账号是king1ko1king,再此说明! fork的项目是:Class-for-Everyone-Java-Server- 作者源项目地址是: ...
- HwUI下载地址
下载地址:HwUI.0.0.1.zip
- css实现div不定宽高垂直水平居中解决方案
在项目中我们经常能碰见然图片垂直水平居中,不定宽高的div垂直水平居中,等等~~ 现在我将介绍我所知道的几种用css来解决的几种方案. 1.父元素text-align:center;display:t ...