LINK:林克卡特树

作为树形dp 这道题已经属于不容易的级别了。

套上了Wqs二分 (反而更简单了 大雾

容易想到还是对树进行联通情况的dp 然后最后结果总和为各个联通块内的直径.

\(f_{i,j}\)表示以i为根的子树内有j条边被删掉 可以发现这个状态难以转移。

需要换个状态 一个比较经典的做法是套用树的直径的那套来做 每个点向上传递单条链或者什么都不传来转移。

传递单条链可以在父亲的那个地方合成一条 然后钦定此条为以x为根的联通内的最大值 那么就可以从x所在父亲的那条边切断了。

或者 传递到父亲那里 再向上传单条链。

传双条链可以默认直接断开 相当于什么都不传。

这样各个联通块都容易dp出来代价了。

但x处还需要开一个状态表示以x在链上且不想上传递链的最大值。

那么只有三种 可以形象的描述为x的度数为0,1,2.

即设\(f_{i,j,0/1,2}\)分别表示此时断开k条链时分别为上述三个状态的最大值。

转移很容易 不再赘述 值得一提的是转移结束时 对于\(f_{x,1},f_{x,2}\)都需要再向\(f_{x,0}\)进行过渡转移。

这是\(n\cdot k^2\)的。

恰好分k个容易想到 Wqs二分 二分斜率切凸包即可。

复杂度\(n\cdot log Mx\)

code
//#include<bits\stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 10000000000000000ll
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define gi(x) scanf("%lf",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define gc(a) scanf("%s",a+1)
#define rep(p,n,i) for(RE int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define fep(n,p,i) for(RE int i=n;i>=p;--i)
#define vep(p,n,i) for(RE int i=p;i<n;++i)
#define pii pair<int,int>
#define mk make_pair
#define RE register
#define P 1000000007
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define EPS 1e-6
#define sq sqrt
#define S second
#define F first
#define mod 1000000007
#define V vector
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
RE int x=0,f=1;RE char ch=getc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
return x*f;
}
const int MAXN=300010;
int n,len,k;
int fa[MAXN];
int lin[MAXN],ver[MAXN<<1],nex[MAXN<<1],e[MAXN<<1];
ll l,r,mid;
struct wy
{
ll s;int v;
inline wy friend operator +(wy a,wy b){return (wy){a.s+b.s,a.v+b.v};}
inline bool friend operator <(wy a,wy b){return a.s<b.s||(a.s==b.s&&a.v<b.v);}
}f[MAXN][3];
inline wy max(wy a,wy b){return a<b?b:a;}
inline void add(int x,int y,int z)
{
ver[++len]=y;
nex[len]=lin[x];
lin[x]=len;
e[len]=z;
}
inline void dfs(int x,int father)
{
fa[x]=father;
go(x)if(tn!=father)dfs(tn,x);
}
inline void dp(int x)
{
f[x][0]=(wy){0,0};f[x][1]=(wy){0,0};f[x][2]=(wy){mid,1};
go(x)if(tn!=fa[x])
{
dp(tn);
f[x][2]=max(f[x][2]+f[tn][0],f[x][1]+f[tn][1]+(wy){mid+e[i],1});
f[x][1]=max(f[x][1]+f[tn][0],f[x][0]+f[tn][1]+(wy){e[i],0});
f[x][0]=f[x][0]+f[tn][0];
}
f[x][0]=max(f[x][0],max(f[x][1]+(wy){mid,1},f[x][2]));
}
int main()
{
//freopen("1.in","r",stdin);
get(n);get(k)+1;
rep(2,n,i)
{
int get(x),get(y),get(z);
add(x,y,z);add(y,x,z);
r+=z>0?z:-z;
}
dfs(1,0);l=-r;
while(l<r)
{
mid=(l+r)>>1;
dp(1);
if(f[1][0].v>=k)r=mid;
else l=mid+1;
}
mid=r;dp(1);
printf("%lld\n",f[1][0].s-mid*k);
return 0;
}

P4383 [八省联考2018]林克卡特树 树形dp Wqs二分的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. POJ3263 Tallest Cow 差分

    题目描述 FJ's N (1 ≤ N ≤ 10,000) cows conveniently indexed 1..N are standing in a line. Each cow has a p ...

  2. JAVA服务实例内存高问题排查及解决

    生产服务内存高问题 问题描述 1."计算中心" 服务在生产环境运行一段时间后,实际占用内存4.8G,业务运行正常,未出现OOM.(本文以此服务进行排查) 2.生产环境的老项目,均出 ...

  3. CentOS7下安装Docker《超详细新手教程》

    1.使用 root 权限登录 Centos.确保 yum 包更新到最新. sudo yum update 2.卸载旧版本(如果安装过旧版本的话) sudo yum remove docker dock ...

  4. mysql numeric

    tinyint  1个字节 smallint 2个字节 mediumint 3个字节 int 4个字节 bigint 8个字节

  5. linux常用命令 总结

    最最常用的快捷键,Tab 键 ,自动补全功能, / 根目录 man 帮助手册:man cd ,查看cd的用法! cd 进入目录:ls -l 列表查看文件详细信息:pwd 当前路径: cp 复制 .rm ...

  6. java 面向对象(四十):反射(四)反射应用一:创建运行时类的对象

    1.代码举例Class<Person> clazz = Person.class; Person obj = clazz.newInstance();System.out.println( ...

  7. Python之爬虫(二十一) Scrapy爬取所有知乎用户信息(下)

    在上一篇文章中主要写了关于爬虫过程的分析,下面是代码的实现,完整代码在:https://github.com/pythonsite/spider items中的代码主要是我们要爬取的字段的定义 cla ...

  8. 数据可视化实例(十): 相关图(matplotlib,pandas)

    相关图 https://datawhalechina.github.io/pms50/#/chapter8/chapter8 导入所需要的库 import numpy as np # 导入numpy库 ...

  9. Unity - NavMeshAgent-GetStart

    Select scene geometry that should affect the navigation – walkable surfaces and obstacles. Check Nav ...

  10. [Android] keytools生成jsk文件以及获取sha1码

    生成jks文件 进入要生的jks文件的路径,打开windows的命令提示符(CMD) keytool -genkey -alias dct -keyalg RSA -keysize 1024 -key ...