@description@

小 L 最近沉迷于塞尔达传说:荒野之息(The Legend of Zelda: Breath of The Wild)无法自拔,他尤其喜欢游戏中的迷你挑战。

游戏中有一个叫做 “LCT” 的挑战,它的规则是这样子的:现在有一个 N 个点的树(Tree),每条边有一个整数边权 \(v_i\),若 \(v_i \ge 0\),表示走这条边会获得 \(v_i\) 的收益;若 \(v_i \lt 0\),则表示走这条边需要支付 \(−v_i\) 的过路费。小 L 需要控制主角 Link 切掉(Cut)树上的恰好 K 条边,然后再连接 K 条边权为 0 边,得到一棵新的树。接着,他会选择树上的两个点 p, q,并沿着树上连接这两点的简单路径从 p 走到 q ,并为经过的每条边支付过路费 / 获取相应收益。

海拉鲁大陆之神 TemporaryDO 想考验一下 Link。他告诉 Link,如果 Link 能切掉合适的边、选择合适的路径从而使总收益-总过路费最大化的话,就把传说中的大师之剑送给他。

小 L 想得到大师之剑,于是他找到了你来帮忙,请你告诉他,Link 能得到的总收益-总过路费最大是多少。

input

输入第一行包含两个正整数 N, K,保证 \(0 \le K \lt N \le 3 \times 10^5\)。

接下来 N − 1 行,每行包含三个整数 \(x_i, y_i, v_i\) ,表示第 i 条边连接图中的 \(x_i, y_i\) 两点,它的边权为 \(v_i\)。保证 \(1 \le x_i, y_i \le N\),\(|v_i| \le 10^6\)。

output

输出一行一个整数,表示答案。

simple input

5 1

1 2 3

2 3 5

2 4 -3

4 5 6

simple output

14

simple explain

一种可能的最优方案为:切掉 (2, 4, −3) 这条边,连接 (3, 4, 0) 这条边,选择 (p, q) = (1, 5)。

提示:题目并不难。(这句话属于题目描述,不是我自己加的 qwq)

@solution@

那句 “题目并不难” 真的是出题人留的。

@part - 1@

先来转换一下题目的要求:恰好选择 K + 1 条不相交的路径(单个点算一条路径),使它们的权值和最大。可以发现这个问题与原问题是等价的。

对个数的限制,通常可以使用带权二分解决。打表观察发现这道题具有带权二分所需要的凸性,所以我们的确可以用带权二分。

我们给每一条路径二分一个附加权值,权值越大选的路径越多,权值越小选的路径越少。

二分的上界为所有边权的最大值,即我选取任何边作为一条路径,都不如把它拆成两个点作为两条路径优秀,路径数量最大。

但是二分的下界并不是所有边权的最小值,实测 -10^9 是可以的,但是理论应该是所有边权的和的相反数……

管它的。调出来就行。

@part - 2@

定义 \(dp[0/1][i]\) 表示以结点 \(i\) 为根的子树中,所能得到的最优解。0 表示不选择 \(i\) 到父亲这条边,1 表示选择 \(i\) 到父亲这条边。再记录 \(cnt[0/1][i]\) 表示取得最优值时所对应的路径数量。

基本思路是:我们仅在路径的顶端(即两个端点的 LCA)将这条路径的贡献计入答案。

转移时维护 \(temp[0/1]\),表示当前根节点向下没有连一条路径所能取到最优解。

这样 \(dp[1][i]\) 可以由 \(temp + dp[1][j]\) 与 \(dp[0][j]\) 两种方法转移过来,其中 j 是 i 的孩子。

而 \(dp[0][i]\) 可以由 \(dp[1][i] + dp[1][j]\) 与 \(dp[0][j]\) 两种方法转移过来。

细节较多,可以参考一下代码。因为我语文太差实在是描述不出来了QAQ。

@accepted code@

#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 300000;
struct edge{
int to; ll dis;
edge *nxt;
}edges[2*MAXN + 5], *adj[MAXN + 5], *ecnt = &edges[0];
void addedge(int u, int v, int w) {
edge *p = (++ecnt);
p->to = v, p->dis = w;
p->nxt = adj[u], adj[u] = p;
p = (++ecnt);
p->to = u, p->dis = w;
p->nxt = adj[v], adj[v] = p;
}
int N, K;
int cnt[2][MAXN + 5];
ll dp[2][MAXN + 5], ans, mid;
void dfs(int rt, int pre) {
ll tmp1; int tmp2;
tmp1 = dp[0][rt] = dp[1][rt] = 0;
tmp2 = cnt[1][rt] = cnt[0][rt] = 0;
if( mid >= 0 )
dp[0][rt] = mid, cnt[0][rt] = 1;
for(edge *p=adj[rt];p!=NULL;p=p->nxt) {
if( p->to == pre ) continue;
dfs(p->to, rt); if( (dp[0][rt] + dp[0][p->to] > dp[1][rt] + dp[1][p->to] + p->dis + mid) || (dp[0][rt] + dp[0][p->to] == dp[1][rt] + dp[1][p->to] + p->dis + mid && cnt[0][rt] + cnt[0][p->to] > cnt[1][rt] + cnt[1][p->to] + 1) )
dp[0][rt] += dp[0][p->to], cnt[0][rt] += cnt[0][p->to];
else dp[0][rt] = dp[1][rt] + dp[1][p->to] + p->dis + mid, cnt[0][rt] = cnt[1][rt] + cnt[1][p->to] + 1; if( (dp[1][rt] + dp[0][p->to] > tmp1 + dp[1][p->to] + p->dis) || (dp[1][rt] + dp[0][p->to] == tmp1 + dp[1][p->to] + p->dis && cnt[1][rt] + cnt[0][p->to] > tmp2 + cnt[1][p->to]) )
dp[1][rt] += dp[0][p->to], cnt[1][rt] += cnt[0][p->to];
else dp[1][rt] = tmp1 + dp[1][p->to] + p->dis, cnt[1][rt] = tmp2 + cnt[1][p->to]; tmp1 += dp[0][p->to], tmp2 += cnt[0][p->to];
}
}
bool check() {
dfs(1, 0); ans = dp[0][1];
return cnt[0][1] >= K + 1;
}
int main() {
scanf("%d%d", &N, &K);
for(int i=1;i<N;i++) {
int x, y, v;
scanf("%d%d%d", &x, &y, &v);
addedge(x, y, v);
}
ll le = ll(-1E9), ri = ll(1E6);
while( le < ri ) {
mid = ll(floor((le + ri)/2.0));
if( check() ) ri = mid;
else le = mid + 1;
}
mid = le; check();
printf("%lld\n", ans - 1LL*le*(K + 1));
}

@details@

这种树形 dp 口胡起来很简单,写起来是真的……不好写。

找二分的下界让我找了好久……

以后有时间可以去总结一下带权二分上下界的套路。

@loj - 2478@「九省联考 2018」林克卡特树的更多相关文章

  1. [loj 2478][luogu P4843]「九省联考 2018」林克卡特树

    传送门 Description 小L 最近沉迷于塞尔达传说:荒野之息(The Legend of Zelda: Breath of The Wild)无法自拔,他尤其喜欢游戏中的迷你挑战. 游戏中有一 ...

  2. Loj #2479. 「九省联考 2018」制胡窜

    Loj #2479. 「九省联考 2018」制胡窜 题目描述 对于一个字符串 \(S\),我们定义 \(|S|\) 表示 \(S\) 的长度. 接着,我们定义 \(S_i\) 表示 \(S\) 中第 ...

  3. LOJ #2473. 「九省联考 2018」秘密袭击

    #2473. 「九省联考 2018」秘密袭击 链接 分析: 首先枚举一个权值W,计算这个多少个连通块中,第k大的数是这个权值. $f[i][j]$表示到第i个节点,有j个大于W数的连通块的个数.然后背 ...

  4. LOJ#2471「九省联考 2018」一双木棋 MinMax博弈+记搜

    题面 戳这里 题解 因为每行取的数的个数是单调不增的,感觉状态数不会很多? 怒而记搜,结果过了... #include<bits/stdc++.h> #define For(i,x,y) ...

  5. 「九省联考 2018」IIIDX 解题报告

    「九省联考 2018」IIIDX 这什么鬼题,送的55分要拿稳,实测有60? 考虑把数值从大到小摆好,每个位置\(i\)维护一个\(f_i\),表示\(i\)左边比它大的(包括自己)还有几个数可以选 ...

  6. LOJ 2743(洛谷 4365) 「九省联考 2018」秘密袭击——整体DP+插值思想

    题目:https://loj.ac/problem/2473 https://www.luogu.org/problemnew/show/P4365 参考:https://blog.csdn.net/ ...

  7. 【LOJ】#2479. 「九省联考 2018」制胡窜

    题解 老了,国赛之前敲一个后缀树上LCT和线段树都休闲的很 现在后缀树上线段树合并差点把我写死 主要思路就是后缀树+线段树合并+容斥,我相信熟练的OIer看到这已经会了 但就是不想写 但是由于我过于老 ...

  8. loj2472 「九省联考 2018」IIIDX

    ref #include <algorithm> #include <iostream> #include <cstdio> using namespace std ...

  9. BZOJ.5249.[九省联考2018]iiidx(贪心 线段树)

    BZOJ LOJ 洛谷 \(d_i\)不同就不用说了,建出树来\(DFS\)一遍. 对于\(d_i\)不同的情况: Solution 1: xxy tql! 考虑如何把这些数依次填到树里. 首先对于已 ...

随机推荐

  1. Mysql千万级访问量架构

    1.HTML 静态化 其实大家都知道,效率最高.消耗最小的就是纯静态化的html页面,所以我们尽可能是我们的网站上的页面采用静态页面来实现,这个最简单的方法其实也是最有效的方法.但是对于大量内容并且频 ...

  2. 服务器安装软件时提示Error launching installer

    一台特殊的服务器 安装tomcat失败 经查询 是语言问题 解决办法: 然后重启

  3. []jnhs]日志套件log4j输出到控制台和文件

    log4j的xml配置文件改为 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j: ...

  4. OSI层次关系

    一.OSI参考模型         今天我们先学习一下以太网最基本也是重要的知识——OSI参考模型. 1.OSI的来源         OSI(Open System Interconnect),即开 ...

  5. 荷畔微风 - 在函数计算FunctionCompute中使用WebAssembly

    WebAssembly 是一种新的W3C规范,无需插件可以在所有现代浏览器中实现近乎原生代码的性能.同时由于 WebAssembly 运行在轻量级的沙箱虚拟机上,在安全.可移植性上比原生进程更加具备优 ...

  6. SVN客户端操作(clean up|commit|update)系统找不到指定的文件

    前天电脑中毒,更新SVN的时候,发现以下错误: Can't open file 'XXXXX\.svn\pristine\7a\7ab8cc591cd8b0425a0e6331cc52756d15ba ...

  7. webpack学习之—— Loaders

    loader 用于对模块的源代码进行转换.loader 可以使你在 import 或"加载"模块时预处理文件.因此,loader 类似于其他构建工具中“任务(task)”,并提供了 ...

  8. 7. 18 test 砍树题解

    (题面保密,内部人员可览) 首先观察题面,可得出如下公式 ∑(ceil(a[i] /d)*d−a[i])≤k 其中,ceil(a[i] /d)表示在需要被砍伐之前所经过的轮数,ceil函数是为了保证一 ...

  9. select @@identity的用法 转

    用select @@identity得到上一次插入记录时自动产生的ID 如果你使用存储过程的话,将非常简单,代码如下:SET @NewID=@@IDENTITY 说明: 在一条 INSERT.SELE ...

  10. Jmeter压测报错:Non HTTP response code: java.net.ConnectExceptionexception的解决办法

    前一段时间进行jmeter压测时,一直报错,查看了下日志才发现报了一堆Non HTTP response code: java.net.ConnectExceptionexception,直接jmet ...