[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. nodeJs的npm报错问题

    1. Failed at the phantomjs-prebuilt@2.1.14 install script 'node install.js'. 解决办法: npm install phant ...

  2. C# list的合并

    转自:https://www.cnblogs.com/liguanghui/archive/2011/11/09/2242309.html List<int> listA = new Li ...

  3. java中对JVM的深度解析、调优工具、垃圾回收

    jdk自带的JVM调优工具 jvm监控分析工具一般分为两类,一种是jdk自带的工具,一种是第三方的分析工具.jdk自带工具一般在jdk bin目录下面,以exe的形式直接点击就可以使用,其中包含分析工 ...

  4. C语言读取配置文件

    自从大学学完C之后,就再也没用过它了, 在网上找代码,七拼八凑之后,终于成形~~勉强能用,不喜勿喷,^_^! int GetValue(const wchar_t *key, wchar_t *val ...

  5. Algorithm——两个排序数组的中位数

    ps:城际的网速还是不错的-

  6. nginx正确服务react-router应用

    如今React应用普遍使用react-router作为路由管理,在开发端webpack自带的express服务器下运行和测试表现均正常,部署到线上的nginx服务器后,还需要对该应用在nginx的配置 ...

  7. windows下生成上传git时需要用的SSH密钥

    参考:Windows上传代码到Github 打开“Git Bash” 输入 ssh-keygen -C "your email" -t rsa 出现如下结果: 成功后,信息里会显示 ...

  8. css动画笔记

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. CentOS7.4 + Ambari 2.6.1.5 + HDP 2.6.4.0 安装部署

    1. 参考说明 参考文档: https://docs.hortonworks.com/HDPDocuments/Ambari-2.6.1.5/bk_ambari-installation/conten ...

  10. CentOS7系列--1.3CentOS7用户管理

    CentOS7用户管理 1. 添加用户 [root@centos7 ~]# useradd jack [root@centos7 ~]# passwd jack Changing password f ...