link

题目大意:给定你 n 个点的一棵树 (边有边权,边权有正负)

你需要移除 k 条边,并连接 k 条权值为 0 的边,使得连接之后树的直径最大

题解:

根据 [POI2015]MOD 那道题,显然我们应该找 k+1 条树上不相交的链,求这些链的长度之和最大值

k = 0 部分分:直接求树的直径

k = 1 部分分:把 MOD 那道题 或者点头网那个第一题粘过来就行了

k <= 100 部分分:我们也考虑树形dp

由于我们只需要把长度累加,我们考虑设 f[i][j][0/1/2] 代表以 i 为根的子树中出现了 j 条链, i 的度数为 0/1/2 的子树链的长度和的最大值 xjb 背包下就行, 复杂度 O (n * k * k)

k == 10000

我们设 \(f(x) = f[1][x][0]\), 即钦定链的数量为 x 时的 dp 结果,最后我们要求的答案就是\(f(k + 1)\)

根据莫名其妙的原因,\(f(x)\) 是单峰函数 并且有最大值

显然我们无法在 \(O(n)\) 的时间复杂度内求出这个值。

我们可以考虑给定一个斜率 \(k\),假设求这个斜率的直线与 \(f(x)\) 图像的切点的坐标很容易,我们就可以发现

假设切点是 \((x_0, f(x_0))\), 那么 \(k\) 和 \(x_0\) 之间是一个单调的关系。

根据斜率是单调的这一性质,我们可以考虑二分斜率,每次求出斜率为 mid 时对应的切点位置,如果切点在需要求的 \(k\) 的左边,我们考虑减小斜率,否则考虑增大斜率。

至于怎么求出切点坐标,我们发现 用斜率为 \(k\) 的直线去切曲线 \(f(x)\) 就相当于 用斜率为 0 的直线去切曲线 \(f(x) - kx\),也就是求 \(f(x) - kx\) 的极值点

我们考虑在 dp 时候解除第二维直径数量的限制,反而在 dp 的值中去维护取得最优解时的链的数量, 并且在每加入一条链时在答案贡献中 -= 二分的斜率 k, 最后得到的答案对应的链的数量即为 x, 答案 + k * x 即为 y

#include <cstdio>
#include <vector>
using namespace std; int n, k;
vector<pair<int, int>> out[300010];
long long mid, ans, pos;
struct dat { int k; long long val; } f[300010][3]; bool operator<(const dat &a, const dat &b) { return a.val != b.val ? (a.val < b.val) : (a.k > b.k); }
dat operator+(const dat &a, const dat &b) { return (dat){a.k + b.k, a.val + b.val}; } void dfs(int x, int fa)
{
f[x][0] = (dat){0, 0}, f[x][1] = (dat){0, 0}, f[x][2] = (dat){1, -mid};
for (pair<int, int> i : out[x]) if (i.first != fa)
{
int v = i.first; dfs(v, x);
f[x][2] = max(f[x][2] + f[v][0], f[x][1] + f[v][1] + (dat){1, i.second - mid});
f[x][1] = max(f[x][1] + f[v][0], f[x][0] + f[v][1] + (dat){0, i.second});
f[x][0] = f[x][0] + f[v][0];
}
f[x][0] = max(f[x][0], max(f[x][2], f[x][1] + (dat){1, -mid}));
} long long check()
{
dfs(1, 0), ans = f[1][0].val;
return pos = f[1][0].k;
} int main()
{
scanf("%d%d", &n, &k), k++;
for (int x, y, z, i = 1; i < n; i++)
{
scanf("%d%d%d", &x, &y, &z);
out[x].push_back(make_pair(y, z));
out[y].push_back(make_pair(x, z));
}
long long l = -1e12, r = -l;
while (l < r)
{
mid = (l + r) >> 1;
if (check() >= k) l = mid + 1;
else r = mid;
}
mid = l, check();
printf("%lld\n", ans + l * k);
return 0;
}

luogu4383 [八省联考2018]林克卡特树(带权二分+dp)的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

  7. BZOJ5252 八省联考2018林克卡特树(动态规划+wqs二分)

    假设已经linkcut完了树,答案显然是树的直径.那么考虑这条直径在原树中是怎样的.容易想到其是由原树中恰好k+1条点不相交的链(包括单个点)拼接而成的.因为这样的链显然可以通过linkcut拼接起来 ...

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

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

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

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

随机推荐

  1. android-tip-SocketException之ETIMEDOUT

    异常出现时间 如果我们有一个长连接,此时网络被关闭,或者暂时失去信号, 此时就会出现此异常. 如果出现此异常,则不得不重连.

  2. 怎样取得selected的option选项的value值

    现在有一id=test的下拉框,怎么拿到选中的那个值呢?   分别使用javascript原生的方法和jquery方法   <select id="test"  name=& ...

  3. [C++] Variable/Hex conversion

    程序编译链接原理预处理:.c -> .i gcc -E hello.c -o hello.i 编译:.i / .c -> .sgcc -S hello.i -o hello.s 汇编:.s ...

  4. code2198 数字三角形WWW

    数字三角形的新变种 设要经过的点为x y,那么dp[x][k] = -Max    k=1~x and k!=y 其他一样:dp[i][j] = max(dp[i-1][j],dp[i-1[j-1]) ...

  5. 巧用渐变色打造精致移动端APP

    渐变色是指某个物体的颜色从明到暗,或由深转浅,或是从一个色彩缓慢过渡到另一个色彩,充满变幻无穷的神秘浪漫气息的颜色.在扁平化设计刚刚兴起时,渐变是设计师们避之不及的设计手法.然而自从Instagram ...

  6. 关于Manifest merger failed : uses-sdk:minSdkVersion 8 cannot be smaller than version 16 declared in lib

    日志有些长,标题显示不完,截图如下: 有图可以知道,是因为在引入的libary里面的build.gradle文件里面的minSdkVersion不一致导致这个问题出现的.修改一致即可.这个问题是在co ...

  7. PHP Windows系统下调用OpenOffice

    项目需要把用户上传的word文档转换为pdf文件,方便用户浏览.经过谷歌百度找到PHP可以使用COM组件调用微软的openoffice来实现文档转换 1,安装OpenOffice 安装OpenOffi ...

  8. linux常用Java程序员使用命令(一)

    pwd 显示当前路径cd 切换目录 . .. ~ls 显示文件(夹) -l 显示详细信息 -a 显示全部,包括隐藏文件(夹) mkdir 创建文件夹 -p 递归创建 touch 创建空白文件 echo ...

  9. XE7 & FMX 那些年我们一起上过的控件:StringGrid 之(1) 自定义标题样式

    FMX下的Grid类控件似乎不太尽如人意,可能是和官方的资料没有跟得上它的发行版本有关系. 以下讨论StringGrid的列表头及对齐方式. 先上个效果图: FMX的列表头估计很多人都是用盒子上流传甚 ...

  10. Exception has been thrown by the target of an invocation

    I'd suggest checking for an inner exception. If there isn't one, check your logs for the exception t ...