题目描述

小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 能得到的 总收益 - 总过路费最大是多少。

输入输出格式

输入格式:

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

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

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

输出格式

输出到文件lct.out 中。

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

输入输出样例

输入样例#1: 复制

5 1
1 2 3
2 3 5
2 4 -3
4 5 6
输出样例#1: 复制

14

说明

【样例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^5105 ; 1 <= xi; yi <= N; |vi| <= 10^6106 。

【提示】

题目并不难。

当时在考场上,,只会$k=0$还挂了一个点。。

题目等价于:在树上选择$k+1$条不相交的链,使其权值和最大。

考虑树形DP(以下的$k$均为$k+1$)

一个很直观的想法是用$f[i][j]$表示第$i$个节点,子树中选了$j$条链的最大价值。

但这样是无法转移的,因此我们要考虑到根节点的情况,

令$f[0/1/2][i][j]$表示$i$号节点的子树中选了$j$条链,根节点不在任何一条链中/作为链的端点/作为两条链的端点的最大值。

更新的时候分三种情况讨论。

但是这样复杂度是$O(N*K)$的,考虑继续优化。

看到这种带$k$限制类的问题,我们尝试wqs二分

按照套路,我们观察$f$数组在不同的$k$下的最优解,不难发现函数是上凸的。严格证明不会,自己意会一下吧。。

按照套路,二分一个边权,加到每条边上,我们可以通过控制边权来控制$k$的大小。如果边权都很小,肯定是少选几条链比较优,如果边权比较大,肯定是多选几条优。

按照套路,如果我们二分到一个边权,在这里恰好选了$k$条链,那么这种选法就是最优的。

判断的时候不需要枚举$k$,因此DP一遍的复杂度为$O(N)$,总复杂度为$O(NlogV)$

还有就是这玩意儿二分的边界比较诡异。。。

// luogu-judger-enable-o2
// luogu-judger-enable-o2
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
#define Pair pair<int, int>
#define int long long
const int MAXN = * 1e5 + ;
using namespace std;
inline int read() {
char c = getchar(); int x = , f = ;
while(c < '' || c > '') {if(c == '-') f = -; c = getchar();}
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * f;
}
struct Node {
int x, y;//x :权值 y:数目
bool operator < (const Node &rhs) const {
return this -> x == rhs.x ? this -> y > rhs.y : this -> x < rhs.x;//tag
}
Node operator + (const Node &rhs) const {
return (Node) {x + rhs.x, y + rhs.y};
}
Node operator + (const int &rhs) const {
return (Node) {x + rhs, y};
}
}f[][MAXN];
int N, K;
struct Edge {
int u, v, w, nxt;
}E[MAXN << ];
int head[MAXN], num = ;
inline void AddEdge(int x, int y, int z) {
E[num] = (Edge) {x, y, z, head[x]};
head[x] = num++;
}
int mid;
Node Plus(Node a) {
return (Node){a.x - mid, a.y + };
}
void dfs(int x, int fa) {
f[][x] = max(f[][x], (Node) {-mid, });
for(int i = head[x]; i != -; i = E[i].nxt) {
int v = E[i].v;
if(v == fa) continue;
dfs(v, x);
f[][x] = max(f[][x] + f[][v], Plus(f[][x] + f[][v] + E[i].w));//把根与子树连起来,会增加一条链
f[][x] = max(f[][x] + f[][v], f[][x] + f[][v] + E[i].w);
f[][x] = f[][x] + f[][v];
//printf("%d %d %d\n", f[2][x].x, f[1][x].x, f[0][x].x);
}
f[][x] = max(f[][x], max(Plus(f[][x]), f[][x]));
}
main() {
#ifdef WIN32
freopen("a.in", "r", stdin);
#endif
memset(head, -, sizeof(head));
N = read(); K = read() + ;
int l = , r = ;
for(int i = ; i < N; i++) {
int x = read(), y = read(), z = read();
AddEdge(x, y, z); AddEdge(y, x, z);
r += abs(z);
}
l = -r;
while(l <= r) {
mid = (l + r) >> ;
memset(f, , sizeof(f));
dfs(, );
if(f[][].y <= K) r = mid - ;
else l = mid + ;
}
mid = l; memset(f, , sizeof(f));
dfs(, );
printf("%lld", f[][].x + mid * K);
return ;
}

洛谷P4383 [八省联考2018]林克卡特树lct(DP凸优化/wqs二分)的更多相关文章

  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. dp凸优化/wqs二分学习笔记(洛谷4383 [八省联考2018]林克卡特树lct)

    qwq 安利一个凸优化讲的比较好的博客 https://www.cnblogs.com/Gloid/p/9433783.html 但是他的暴力部分略微有点问题 qwq 我还是详细的讲一下这个题+这个知 ...

  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. P4383 [八省联考2018]林克卡特树 树形dp Wqs二分

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

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

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

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

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

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

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

随机推荐

  1. 基础架构之GitLab

    Git几乎是软件开发人员的必备工具了,关于代码管理,公司都一般都会搭建自己的仓库,关于GitLab的详细介绍参见官方网站详见 https://about.gitlab.com,这篇文章主要介绍安装及使 ...

  2. 09_dubbo服务发布原理

    [ 启动服务的日志分析 ] 1.暴露本地服务 Export dubbo service com.alibaba.dubbo.demo.DemoService to local registry, du ...

  3. SQL Server ->> PARSE函数

    这个函数和TRY_PARSE一起从SQL Server 2012引入.它的存在是因为TRY_PARSE一旦遇到无法成功转换就会以NULL值返回,而如果你希望以报错的形式,你就可以用PARSE. 比如 ...

  4. ubuntu安装最新版node和npm

    1.先在系统上安装好nodejs和npm           sudo apt-get install nodejs-legacy sudo apt-get install npm     2.升级n ...

  5. eclipse中对Hadoop项目进行mvn clean install时报错的处理

    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-clean-plugin:2.5:clean (default-clean) ...

  6. r.js压缩打包(require + backbone)项目开发文件

    最近项目稳定了一点,之前一直没空关注的开发文件压缩打包问题也有时间来解决了 AMD模块化开发中的代码压缩打包工具——r.js 环境搭建基于nodejs:用于AMD模块化开发中的项目文件压缩打包,不是A ...

  7. ABAP SICF服务和Java Servlet的比较

    In my opinion ABAP ICF handler and Java Servlet play the same role in enhancement which enables your ...

  8. bootstrap table footerFormatter用法 统计列求和 sum、average等

    其实上一篇blog里已经贴了代码,简单解释一下吧: 1.showFooter: true,很重要,设置footer显示: $(cur_table).bootstrapTable({ url: '/et ...

  9. apache log4j-1.2.15的使用

    1.这个log4j的下载 下载 http://www.apache.org/dyn/closer.cgi/logging/log4j/1.2.15/apache-log4j-1.2.15.zip 2. ...

  10. SpringMVC 如何定义类型转换器

    举例说明, 将一个字符串转换成的 User 类型. 例如将字符串 1-zcd-1234-zcd@163.com-1999/12/12  转换成User 类型. 一.实体类 public class U ...