洛谷P4383 [八省联考2018]林克卡特树lct(DP凸优化/wqs二分)
题目描述
小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 解释】
一种可能的最优方案为:切掉(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二分)的更多相关文章
- 洛谷 4383 [八省联考2018]林克卡特树lct——树形DP+带权二分
题目:https://www.luogu.org/problemnew/show/P4383 关于带权二分:https://www.cnblogs.com/flashhu/p/9480669.html ...
- 洛谷.4383.[八省联考2018]林克卡特树lct(树形DP 带权二分)
题目链接 \(Description\) 给定一棵边带权的树.求删掉K条边.再连上K条权为0的边后,新树的最大直径. \(n,K\leq3\times10^5\). \(Solution\) 题目可以 ...
- dp凸优化/wqs二分学习笔记(洛谷4383 [八省联考2018]林克卡特树lct)
qwq 安利一个凸优化讲的比较好的博客 https://www.cnblogs.com/Gloid/p/9433783.html 但是他的暴力部分略微有点问题 qwq 我还是详细的讲一下这个题+这个知 ...
- P4383 [八省联考2018]林克卡特树lct
题目链接 题意分析 一句话题意就是 : 让你选出\((k+1)\)条不相交的链 使得这些链的边权总和最大 (这些链可以是点) 我们考虑使用树形\(DP\) \(dp[i][j][0/1/2]\)表示以 ...
- P4383 [八省联考2018]林克卡特树lct 树形DP+凸优化/带权二分
$ \color{#0066ff}{ 题目描述 }$ 小L 最近沉迷于塞尔达传说:荒野之息(The Legend of Zelda: Breath of The Wild)无法自拔,他尤其喜欢游戏中的 ...
- P4383 [八省联考2018]林克卡特树 树形dp Wqs二分
LINK:林克卡特树 作为树形dp 这道题已经属于不容易的级别了. 套上了Wqs二分 (反而更简单了 大雾 容易想到还是对树进行联通情况的dp 然后最后结果总和为各个联通块内的直径. \(f_{i,j ...
- LuoguP4383 [八省联考2018]林克卡特树lct
LuoguP4383 [八省联考2018]林克卡特树lct https://www.luogu.org/problemnew/show/P4383 分析: 题意等价于选择\(K\)条点不相交的链,使得 ...
- [八省联考2018]林克卡特树lct——WQS二分
[八省联考2018]林克卡特树lct 一看这种题就不是lct... 除了直径好拿分,别的都难做. 所以必须转化 突破口在于:连“0”边 对于k=0,我们求直径 k=1,对于(p,q)一定是从p出发,走 ...
- luoguP4383 [八省联考2018]林克卡特树(树上dp,wqs二分)
luoguP4383 [八省联考2018]林克卡特树(树上dp,wqs二分) Luogu 题解时间 $ k $ 条边权为 $ 0 $ 的边. 是的,边权为零. 转化成选正好 $ k+1 $ 条链. $ ...
随机推荐
- 用CSS隐藏页面元素的5种方法
1.opacity设置一个元素的透明度只是从视觉上隐藏元素,对页面布局还是有影响,读屏软件会原样读出 2.visibility设置为hidden将隐藏我们的元素,对网页布局还是起作用,子元素也会被隐藏 ...
- 第4课 简易浏览器-WebViewer组件的使用方法
做一个手机浏览器,需要哪些组件呢? 一.组件设计 二.组件属性及命名修改 三.逻辑设计 1.导航按钮代码:前进.后退.主页 2.访问网页按钮 1)根据用户在地址栏输入的地址书写,判断书写中是否含有“h ...
- Raspberry 安装vstudio
Visual Studio Code微软公司推出的一款轻量级的Visual Studio风格的跨平台的IDE.当然,除了Windows,OSX,还能在树莓派上使用.目前树莓派上可用的IDE真不多,VS ...
- HTML,javascript,image等加载,DOM解析,js执行生命周期
- 扩展javascript原生对象
原文地址: http://javascript.info/tutorial/native-prototypes 原生的javascript 对象在prototypes里面保存他们可用的方法. 比如,当 ...
- XML布局之路
XML布局存放在工程文件的res/layout目录下.安卓和PC端的界面布局有用到. 常用的布局方式,线性布局:LinearLayout 表格布局:TableLayout 帧布局 :FrameLay ...
- Struts2学习-Ioc学习-spring
1.面向对象写法(带着面向过程的思维)电脑 computer = new 电脑(); [电脑代码中 new 打印机()]computer.打印文本("hello 140"); 电脑 ...
- 在IE浏览器输入测试servlet程序报:HTTP Status 404(The requested resource is not available)错
一.HTTP Status 404(The requested resource is not available)异常主要是路径错误或拼写错误造成的,请按以下步骤逐一排查: 1.未部署Web应用 2 ...
- docker中自定ingress网络
在某些时候,docker自动生成的ingress网络会与服务器上已经存在的网络产生冲突,这个时候,你需要自定义ingress. 在自定义前,你需要删除所有有端口发布的服务. 使用命令docker ne ...
- bootstrap table footerFormatter用法 统计列求和 sum、average等
其实上一篇blog里已经贴了代码,简单解释一下吧: 1.showFooter: true,很重要,设置footer显示: $(cur_table).bootstrapTable({ url: '/et ...