$ \color{#0066ff}{ 题目描述 }$

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

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

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

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

\(\color{#0066ff}{输入格式}\)

从文件lct.in 中读入数据。

输入第一行包含两个正整数N; K,保证0 <= K < N <= 3*\(10^5\)。

接下来N - 1 行,每行包含三个整数xi; yi; vi,表示第i 条边连接图中的xi; yi 两点, 它的边权为vi。

\(\color{#0066ff}{输出格式}\)

输出到文件lct.out 中。

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

\(\color{#0066ff}{输入样例}\)

5 1
1 2 3
2 3 5
2 4 -3
4 5 6

\(\color{#0066ff}{输出样例}\)

14

\(\color{#0066ff}{数据范围与提示}\)

【样例1 解释】

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

• 对于10% 的数据,k = 0 ;

• 对于另外10% 的数据,k = 1 ;

• 对于另外15% 的数据,k = 2 ;

• 对于另外25% 的数据,k <= 100 ;

• 对于其他数据,没有特殊约定。

对于全部的测试数据,保证有1 <= N <= 3 * \(10^5\); 1 <= xi; yi <= N; |vi| <= \(10^6\) 。

【提示】

题目并不难。

\(\color{#0066ff}{题解}\)

带权二分,这篇题解写的比较详细,转载自 EternalAlexander

#include<bits/stdc++.h>
#define LL long long
LL in() {
char ch; LL x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
const int maxn = 3e5 + 100;
struct node {
LL mx, k;
node(LL mx = 0, LL k = 0): mx(mx), k(k) {}
friend node operator + (const node &a, const node &b) { return node(a.mx + b.mx, a.k + b.k); }
friend bool operator < (const node &a, const node &b) { return (a.mx < b.mx || (a.mx == b.mx && a.k < b.k)); }
}f[maxn][3];
struct EDGE {
int to; LL dis;
EDGE *nxt;
EDGE(int to = 0, LL dis = 0, EDGE *nxt = NULL): to(to), dis(dis), nxt(nxt) {}
};
EDGE *head[maxn];
LL n, k, mid, ans, B; void dfs(int x, int fa) {
f[x][0] = f[x][1] = node(0, 0);
f[x][2] = node(-mid, 1);
for(EDGE *i = head[x]; i; i = i->nxt) {
if(i->to == fa) continue; dfs(i->to, x);
f[x][2] = std::max(f[x][2] + f[i->to][0], f[x][1] + f[i->to][1] + node(i->dis - mid, 1));
f[x][1] = std::max(f[x][1] + f[i->to][0], f[x][0] + f[i->to][1] + node(i->dis, 0));
f[x][0] = f[x][0] + f[i->to][0];
}
f[x][0] = std::max(f[x][0], std::max(f[x][1] + node(-mid, 1), f[x][2]));
} void add(int from, int to, int dis) { head[from] = new EDGE(to, dis, head[from]); }
LL ok() {
dfs(1, 0);
B = f[1][0].mx;
return f[1][0].k;
}
int main() {
n = in(), k = in() + 1;
LL l, r = 0;
LL x, y, z;
for(int i = 1; i < n; i++) {
x = in(), y = in(), z = in();
add(x, y, z), add(y, x, z);
r += z > 0? z : -z;
}
l = -r;
while(l <= r) {
mid = (l + r) >> 1;
if(ok() >= k) l = mid + 1, ans = mid;
else r = mid - 1;
}
mid = ans;
ok();
printf("%lld\n", B + ans * k);
return 0; }

P4383 [八省联考2018]林克卡特树lct 树形DP+凸优化/带权二分的更多相关文章

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

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

  2. 洛谷.4383.[八省联考2018]林克卡特树lct(树形DP 带权二分)

    题目链接 \(Description\) 给定一棵边带权的树.求删掉K条边.再连上K条权为0的边后,新树的最大直径. \(n,K\leq3\times10^5\). \(Solution\) 题目可以 ...

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

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

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

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

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

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

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

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

  7. P4383 [八省联考2018]林克卡特树 树形dp Wqs二分

    LINK:林克卡特树 作为树形dp 这道题已经属于不容易的级别了. 套上了Wqs二分 (反而更简单了 大雾 容易想到还是对树进行联通情况的dp 然后最后结果总和为各个联通块内的直径. \(f_{i,j ...

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

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

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

    bzoj(上面可以下数据) luogu description 在树上选出\(k\)条点不相交的链,求最大权值. 一个点也算是一条退化的链,其权值为\(0\). sol 别问我为什么现在才写这题 首先 ...

随机推荐

  1. 混合开发之DSBridge(同时支持Android和iOS)

    什么是 Javascript bridge 随着h5的不断普及及优化,以及移动端对动态化的需求越来越大,开发者经常需要在app中嵌入一些网页,然后会在web和native之间进行交互,如传递数据,调用 ...

  2. DBArtist之Oracle入门第4步: Oracle创建数据库

    刚开始进去后,我是懵逼的状态,不知道要干嘛,之前常用的是MSSQL,感觉两者还是有区别的: oracle中:1.查询数据库名:select name,dbid from v$database;或者sh ...

  3. OceanBase

    OceanBase 编辑 本词条缺少名片图,补充相关内容使词条更完整,还能快速升级,赶紧来编辑吧! OceanBase是一个支持海量数据的高性能分布式数据库系统,实现了 数千亿条记录.数百TB数据上的 ...

  4. ansible的ad-hoc模式

    一.什么是ad-hoc模式 ansible中有两种模式,分别是ad-hoc模式和playbook模式 ad-hoc简而言之,就是"临时命令" 二.ad-hoc模式使用的场景 场景一 ...

  5. ubuntu14.04 64 位 vmware tools 问题

    当提示说open-vm-tools版本太低时可以这样解决 1.sudo apt-get autoremove open-vm-dkms open-vm-tools --purge 2.安装vmware ...

  6. Openssl rand命令

    一.简介 rand命令用来产生伪随机字节,随机数字产生器需要一个seed,在没有/dev/srandom系统下的解决方法是自己做一个~/.rnd文件 二.语法 openssl rand [-out f ...

  7. [SoapUI] Loop a test with different sets of data

  8. BAdi:BOM_UPDATE - Check update for BOM Save

    需求:BOM中替代项目组要求同一组比率之和必须是100. 实现:BAdi:BOM_UPDATE METHOD if_ex_bom_update~change_at_save. DATA: ls_wa ...

  9. Perl 学习笔记-模块

    1.Perl模块介绍 2个来源, 一个是随Perl发行版本一同打包, 只要安装了Perl就可以使用;  另一种是需要从CPAN上下载,自己安装.   寻找模块之前, 先检查系统上是否已经安装过了,   ...

  10. SQL高性能分页

    分页的场景就不多说了,无处不在. 方法一:利用row_number() with C as ( select ROW_NUMBER() over(order by orderdate,orderid) ...