目录

  • @description@
  • @solution@
    • @part - 1@
    • @part - 2@
  • @accepted code@
  • @details@


@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 口胡起来很简单,写起来是真的……不好写。

找二分的下界让我找了好久……
以后有时间可以去总结一下带权二分上下界的套路。

转载于:https://www.cnblogs.com/Tiw-Air-OAO/p/10215044.html

@loj - 2478@「九省联考 2018」林克卡特树相关推荐

  1. LibreOJ #2478.「九省联考 2018」林克卡特树 树形dp+带权二分

    题意 给出一棵n个节点的树和k,边有边权,要求先从树中选k条边,然后把这k条边删掉,再加入k条边权为0的边,满足操作完后的图仍然是一棵树.问新树的带权直径最大是多少. n,k≤3∗105n,k≤3∗1 ...

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

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

  3. [博弈] LOJ#2471. 「九省联考 2018」一双木棋

    考虑暴力. 每次枚举放哪个位置,设已经放了棋子的位置集合为 SSS,fS" role="presentation">fSfSf_S 表示当前放置情况为 SSS 时, ...

  4. 「九省联考 2018」一双木棋

    「九省联考 2018」一双木棋 题目描述 菲菲和牛牛在一块 \(n\) 行 \(m\) 列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手. 棋局开始时,棋盘上没有任何棋子,两人轮流在格子上落子,直到填满 ...

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

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

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

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

  7. [九省联考2018]IIIDX 贪心 线段树

    ~~~题面~~~ 题解: 一开始翻网上题解看了好久都没看懂,感觉很多人都讲得不太详细,所以导致一些细节的地方看不懂,所以这里就写详细一点吧,如果有不对的or不懂的可以发评论在下面. 首先有一个比较明显 ...

  8. 洛谷P4364 [九省联考2018]IIIDX(线段树)

    传送门 题解看得--很--迷? 因为取完一个数后,它的子树中只能取权值小于等于它的数.我们先把权值从大到小排序,然后记$a_i$为他左边(包括自己)所有取完他还能取的数的个数.那么当取完一个点$x$的 ...

  9. 「Luogu4363/BZOJ5248」[九省联考2018]一双木棋chess

    「Luogu4363/BZOJ5248」[九省联考2018]一双木棋chess 学校省选模拟居然拿九省联考来考 然而我还是\(too\space young\),搞不懂什么叫最优 让二者的答案最接近可 ...

最新文章

  1. D - ABC Conjecture Gym - 102798D
  2. 认识什么是运维中的CI/CD---持续集成交付工作笔记001
  3. Mac废纸篓无法清空怎么办?
  4. 如果您能天天读上一遍,就能和老外对话了!
  5. java聚合支付之建行
  6. word文档压缩文件大小
  7. 各公司用户画像技术案例分享
  8. rclone 实现 GoogleDrive 同步至 OneDrive
  9. dbm与mysql区别_dbm数据库
  10. QuickCHM 2.6中“不支持此接口”错误的解决
  11. 饭饭科普47 — 什么是区块链
  12. 微信小程序学习之路——API用户信息
  13. 关于固态硬盘的数据擦除
  14. Hibernate第四篇【集合映射、一对多和多对一】
  15. 前端白屏问题_前端性能优化之白屏时间
  16. 关于实现QQ来消息时的黄色效果,即闪烁窗体
  17. delphi 操作excel(全)
  18. 读《微波工程(第三版)》笔记 (4:波方程和基本平面波的解)
  19. mysql meb物理备份脚本
  20. Win10安装Rtree包报错:OSError: could not find or load spatialindex_c-64.dll

热门文章

  1. Ubuntu安装flash
  2. 地图配色及网络地图比较
  3. 把握SDN研发方向,展望未来发展趋势
  4. 穿上钢铁侠战衣变身钢铁侠,现代表示我做到了!
  5. 如何启用计算机的无线功能键在哪,启动无线功能开关在哪
  6. GAPIT 3.0:全基因组关联分析与预测软件最新版发布
  7. 企业从无到有,云账户CEO大谈创业时代的创业者思维
  8. 酷派7296刷机包 高仿IOS美化 细节精仿 流畅 可能是你心中完美的ROM
  9. linux获取触控板信息,关于linux:Linux-下通过命令行和脚本开关笔记本触控板和其他输入外设...
  10. 业务实战记录(1):帮业务人员做道Excel题