P4383 [八省联考2018]林克卡特树(树形dp+wqs二分)

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

题目大意:给定一棵有负权边的树,现在必须恰好删去kkk条边,并加上恰好kkk条权值为000的边,要求最大化它的直径长度。

首先考虑删去KKK条边的效果:把整棵树变成k+1k+1k+1个连通块
然后用0权变把这几个连通块连起来,当k+1k+1k+1个连通块已经确定后有个显然的结论:用kkk条边把他们连接后的最大直径长度就是k+1k+1k+1个连通块的直径代数求和。
方法是将k+1k+1k+1条直径首位依次相连即可,显然不可能有比它更大的直径。这个方案引导我们转化问题:寻找k+1k+1k+1条互不相交的链使得链的长度之和最大化

于是可设计树形dp
状态表示:fu,j,0/1/2f_{u,j,0/1/2}fu,j,0/1/2考虑以uuu为根的子树,当前选择了jjj互不相交完整的链,并且uuu节点的度数为0/1/20/1/20/1/2的最优解。
状态转移:
首先说明答案就是max⁡(f1,k+1,0,f1,k,1,f1,k+1,2)\max(f_{1,k+1,0},f_{1,k,1},f_{1,k+1,2})max(f1,k+1,0,f1,k,1,f1,k+1,2),注意f1,k,1f_{1,k,1}f1,k,1这个值,我们jjj表示完整的链,而还有一条以节点111为端点的一条链我们不算它为完整的链,因为他可以和父亲节点合并合成新的链,也就是f1,k,1f_{1,k,1}f1,k,1实际上有k+1k+1k+1条链:kkk条完整,1条以节点111为端点的链。

首先我们让每课子树结束后fv,j,0=max⁡(fv,j,0,fv,j−1,1,fv,j,2)f_{v,j,0}=\max(f_{v,j,0},f_{v,j-1,1},f_{v,j,2})fv,j,0=max(fv,j,0,fv,j1,1,fv,j,2)表示在子树uuu中选择jjj条链的最优解。于是有以下更新:
考虑uuu节点以及它的一个儿子节点vvv

  • fu,j+k,0=fu,j,0+fv,k,0f_{u,j+k,0}=f_{u,j,0}+f_{v,k,0}fu,j+k,0=fu,j,0+fv,k,0
  • fu,j+k,1=max⁡(fu,j,1+fv,k,0,fu,k,0+fv,k,1+wu→v)f_{u,j+k,1}=\max(f_{u,j,1}+f_{v,k,0},f_{u,k,0}+f_{v,k,1}+w_{u\to v})fu,j+k,1=max(fu,j,1+fv,k,0,fu,k,0+fv,k,1+wuv)
  • fu,j+k,2=fu,j,2+fv,k,0;fu,j+k+1,2=fu,j,1+fv,k,1+wu→vf_{u,j+k,2}=f_{u,j,2}+f_{v,k,0};f_{u,j+k+1,2}=f_{u,j,1}+f_{v,k,1}+w_{u\to v}fu,j+k,2=fu,j,2+fv,k,0;fu,j+k+1,2=fu,j,1+fv,k,1+wuv

sz优化以及边界优化后时间复杂度O(nk)O(nk)O(nk)

#include<map>
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
using ll=long long;
using pii=pair<int,int>;
using pli=pair<long long,int>;
constexpr int N=300010,M=600010;
constexpr ll INF=0x3f3f3f3f3f3f3f3f;
int h[N],e[M],ne[M],w[M],idx;
void add(int a,int b,int c){e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;}
int n,m,sz[N];
ll f[N][105][3],g[105][3];
void dfs(int u,int fa)
{f[u][0][0]=0;f[u][0][1]=0;f[u][1][2]=0;  //一个点看成自环sz[u]=1;for(int i=h[u];i!=-1;i=ne[i]){int v=e[i];if(v==fa) continue;dfs(v,u);for(int j=0;j<=sz[u]+sz[v]&&j<=m;j++) g[j][0]=g[j][1]=g[j][2]=-INF;for(int j=0;j<=sz[u]&&j<=m;j++)for(int k=0;k<=sz[v]&&k+j<=m;k++){g[j+k][0]=max(g[j+k][0],f[u][j][0]+f[v][k][0]);g[j+k][1]=max(g[j+k][1],max(f[u][j][1]+f[v][k][0],f[u][j][0]+f[v][k][1]+w[i]));g[j+k][2]=max(g[j+k][2],f[u][j][2]+f[v][k][0]);if(j+k+1<=m) g[j+k+1][2]=max(g[j+k+1][2],f[u][j][1]+f[v][k][1]+w[i]);}for(int j=0;j<=sz[u]+sz[v]&&j<=m;j++)f[u][j][0]=g[j][0],f[u][j][1]=g[j][1],f[u][j][2]=g[j][2];sz[u]+=sz[v];}for(int j=0;j<=sz[u]&&j<=m;j++){f[u][j][0]=max(f[u][j][0],f[u][j][2]);if(j) f[u][j][0]=max(f[u][j][0],f[u][j-1][1]);}
}
int main()
{ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);cin>>n>>m; ++m;memset(h,-1,sizeof h);memset(f,-0x3f,sizeof f);for(int i=1;i<n;i++){int a,b,c;cin>>a>>b>>c;add(a,b,c),add(b,a,c);}dfs(1,0);cout<<f[1][m][0]<<'\n';return 0;
}

wqs二分优化待补
upd:2021/2/28
打表观察可知:fu,j,0/1/2(j)f_{u,j,0/1/2}(j)fu,j,0/1/2(j)这个函数也就是在坐标轴上的点(j,f(j))(j,f(j))(j,f(j))形成的图像是凸的,于是可以采用wqs二分的优化技巧去掉dp数组第二维选择个数的限制。
由于wqs二分的一些细节,需要用一个结构体记录,分别表示值和选择的个数,值相同我们尽量选择个数少的方案。

#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
using ll=long long;
using pii=pair<int,int>;
using pli=pair<long long,int>;
constexpr int N=300010,M=600010;
constexpr ll INF=0x3f3f3f3f3f3f3f3f;
int h[N],e[M],ne[M],w[M],idx;
void add(int a,int b,int c){e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;}
int n,m;
struct node
{ll v;int cnt;bool operator<(const node& o)const{return v<o.v||v==o.v&&cnt>o.cnt;}bool operator>(const node& o)const{return v>o.v||v==o.v&&cnt<o.cnt;}node operator+(const node& o)const{return (node){v+o.v,cnt+o.cnt};}
}f[N][3];
void dfs(int u,int fa,ll delta)
{f[u][0]=(node){0,0};f[u][1]=(node){0,0};f[u][2]=(node){-delta,1};for(int i=h[u];i!=-1;i=ne[i]){int v=e[i];if(v==fa) continue;dfs(v,u,delta);          //这里没用备份数组 注意顺序一定不能改f[u][2]=max(f[u][2],max(f[u][1]+f[v][1]+(node){w[i]-delta,1},f[u][2]+f[v][0]));f[u][1]=max(f[u][1],max(f[u][1]+f[v][0],f[u][0]+f[v][1]+(node){w[i],0}));f[u][0]=max(f[u][0],f[u][0]+f[v][0]);}f[u][0]=max(max(f[u][0],f[u][2]),(node){f[u][1].v-delta,f[u][1].cnt+1});
}
bool check(ll x)
{dfs(1,0,x);return f[1][0].cnt<=m;
}
int main()
{ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);cin>>n>>m; ++m;memset(h,-1,sizeof h);memset(f,-0x3f,sizeof f);for(int i=1;i<n;i++){int a,b,c;cin>>a>>b>>c;add(a,b,c),add(b,a,c);}ll l=-1e12,r=1e12;while(l<r){ll mid=l+r>>1;if(check(mid))  r=mid;else l=mid+1;}check(l);cout<<1ll*m*l+f[1][0].v<<'\n';return 0;
}

第一道洛谷黑题,明天开学起飞
要加油哦~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/318975.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

bzoj4025-二分图【线段树分治,并查集】

正题 题目链接:https://darkbzoj.tk/problem/4025 题目大意 nnn个点mmm条边&#xff0c;每条边会在一个TTT以内的时间段内出现&#xff0c;对于任意一个TTT以内的时刻求图是否是一个二分图。 1≤n,T≤105,1≤m≤21051\leq n,T\leq 10^5,1\leq m\leq 2\times 10^51≤n,T≤105,1…

牛客题霸 [删除有序链表中重复的元素] C++题解/答案

牛客题霸 [删除有序链表中重复的元素] C题解/答案 题目描述 删除给出链表中的重复元素&#xff08;链表中元素从小到大有序&#xff09;&#xff0c;使链表中的所有元素都只出现一次 例如&#xff1a; 给出的链表为1\to1\to21→1→2,返回1 \to 21→2. 给出的链表为1\to1\to 2 \…

我在微软做研发 | 亚洲创新的科研之力

丹棱君有话说&#xff1a;在庆祝微软亚洲研究院成立 20 周年之际&#xff0c;微软亚洲研究院的几位科学家向我们讲述了在这里&#xff0c;如何以科研热情推动了技术创新。走进微软亚洲研究院的办公园区&#xff0c;便会被这里安静的研究氛围所包围。在当今越来越多追求速度、提…

codeforces1208 F. Bits And Pieces(SOS DP)

heyuhhh高维前缀和总结 SOS DP SOS Dynamic Programming [Tutorial] 之前写过相关的题目枚举子集dp 枚举子集 F[mask]∑i∈maskA[i],i&maskiF[mask]\sum_{i\in mask}A[i],i\&maskiF[mask]i∈mask∑​A[i],i&maski 方法1&#xff0c;O(4n)O(4^n)O(4n)暴力枚举 for(…

P5956-[POI2017]Podzielno【数学】

正题 题目链接:https://www.luogu.com.cn/problem/P5956 题目大意 BBB进制下&#xff0c;给出序列aaa&#xff0c;aia_iai​表示数字iii有多少个。求一个最大的XXX在BBB进制下&#xff0c;由给出的数字组成&#xff08;不一定要用完&#xff09;&#xff0c;且其是B−1B-1B−1…

牛客题霸 [回文数字(palindrome-number)] C++题解/答案

牛客题霸 [回文数字] C题解/答案 题解: 首先&#xff1a;负数不可以回文&#xff08;起码看着就不对称&#xff09; 然后我们将x翻转&#xff0c;很简单sumsum*10x%10; 因为x最终会变成0&#xff0c;所以用y先存一下x 最后比较sum与y是否相等 面试&#xff1a; class Solut…

codeforces1494 D. Dogeforces(构造)

昨晚1h20min做完了3个题&#xff0c;看下排名600左右&#xff0c;感觉稳可以上分了&#xff0c;于是看了下D构造&#xff1f;感觉不太会没细想于是看了看E感觉好像和之前有一个题目很像&#xff08;那个题我讨论了好长时间&#xff09;&#xff0c;然后磨叽磨叽还有20min感觉写…

P4126-[AHOI2009]最小割【网络流,tarjan】

正题 题目链接:https://www.luogu.com.cn/problem/P4126 题目大意 给出nnn个点mmm条边的一张有向图和起点终点。对于每条边求其是否是最小割的可行割/必须割 1≤n≤4000,1≤m≤600001\leq n\leq 4000,1\leq m\leq 600001≤n≤4000,1≤m≤60000 解题思路 一些结论吧&#xff…

调试.NET CORE代码

前言core也用了很长一段时间了&#xff0c;发现很多小伙伴不知道如何调试core的代码。可想而知&#xff0c;以前使用mvc的时候&#xff0c;不需要发布代码&#xff0c;直接iis地址指向项目源码&#xff0c;然后附加到进程w3wp.exe就可以调试了。在core的项目里面已经不能这样玩…

牛客题霸 [二叉树中是否存在节点和为指定值的路径] C++题解/答案

牛客题霸 [二叉树中是否存在节点和为指定值的路径] C题解/答案 题目描述 给定一个二叉树和一个值\ sum sum&#xff0c;判断是否有从根节点到叶子节点的节点值之和等于\ sum sum 的路径&#xff0c; 例如&#xff1a; 给出如下的二叉树&#xff0c;\ sum22 sum22&#xff0c;…

P4292-[WC2010]重建计划【长链剖分,线段树,0/1分数规划】

正题 题目链接:https://www.luogu.com.cn/problem/P4292 题目大意 给出nnn个点的一棵树&#xff0c;然后求长度在[L,U][L,U][L,U]之间的一条路径的平均权值最大。 解题思路 先上二分0/10/10/1分数规划&#xff0c;然后变成求最长在[L,U][L,U][L,U]之间的路径。 很经典的点分…

HDU4035 Maze(树上期望)

Maze 状态表示&#xff1a;fuf_ufu​表示在uuu节点走出迷宫期望次数&#xff0c;dud_udu​表示度数 首先很容易想到下面式子fukuf1(1−ku−eu)∑u→vfv1duf_uk_uf_1(1-k_u-e_u)\frac{\sum _{u\to v}f_v1}{d_u}fu​ku​f1​(1−ku​−eu​)du​∑u→v​fv​1​ 每个节点有一个类…

从头开始学eShopOnContainers——Visual Studio 2017环境配置

一、安装和配置Docker环境1、安装Docker CE for Windows从官方网站下载并安装&#xff0c;https://docs.docker.com/docker-for-windows/install/。默认情况下Docker for Windows使用Hyper-V运行Linux VM。 如果您没有安装/启用Hyper-V&#xff0c;它将被安装&#xff0c;您可能…

牛客题霸 [判断二叉树是否对称] C++题解/答案

[牛客题霸 [判断二叉树是否对称] C题解/答案](https://www.nowcoder.com/practice/1b0b7f371eae4204bc4a7570c84c2de1?tpId117&&tqId34937&rp1&ru/ta/job-code-high&qru/ta/job-code-high/question-ranking) 题目描述 给定一棵二叉树&#xff0c;判断琪…

ASP.NET Core 生成验证码

点击蓝字关注我使用验证码保护网站免受垃圾信息的选择有很多&#xff0c;比如Google ReCaptcha和captcha.com。这两者都可以整合到ASP.NET Core应用中去。然而&#xff0c;如果你出于某些原因&#xff0c;仍然希望自己写验证码&#xff0c;例如你下网站需要在中国大陆使用&…

P4756-Added Sequence【斜率优化】

正题 题目链接:https://www.luogu.com.cn/problem/P4756 题目大意 给出序列aaa&#xff0c;设f(l,r)∣∑ilrai∣f(l,r)|\sum_{il}^ra_i|f(l,r)∣∑ilr​ai​∣。 mmm次询问若序列aaa全部加上某个数xxx&#xff0c;求最大的f(l,r)f(l,r)f(l,r)。 1≤n,m≤21051\leq n,m\leq 2\…

P4564 [CTSC2018]假面(期望)

P4564 [CTSC2018]假面 首先容易看出结界技能对第二问敌方剩余生命值期望没有影响。 如何求出第iii个人的剩余生命值期望&#xff1f; 只需要根据Ei∑j0aijfi,jE_i\sum_{j0}^{a_i}jf_{i,j}Ei​∑j0ai​​jfi,j​ 预处理fi,jf_{i,j}fi,j​&#xff1a;第iii个人的剩余生命值为j…

牛客题霸 [连续子数组的最大和] C++题解/答案

牛客题霸 [连续子数组的最大和] C题解/答案 题目描述 HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含…

P4234-最小差值生成树【LCT】

正题 题目链接:https://www.luogu.com.cn/problem/P4234 题目大意 给出nnn个点mmm条边的一张图。求一棵生成树使得最大边权减去最小边权最小。 1≤n≤5104,1≤m≤21051\leq n\leq 5\times 10^4,1\leq m\leq 2\times 10^51≤n≤5104,1≤m≤2105 解题思路 按照边权排序&#x…

【.NET Core项目实战-统一认证平台】第六章 网关篇-自定义客户端授权

上篇文章【.NET Core项目实战-统一认证平台】第五章 网关篇-自定义缓存Redis 我们介绍了网关使用Redis进行缓存&#xff0c;并介绍了如何进行缓存实现&#xff0c;缓存信息清理接口的使用。本篇我们将介绍如何实现网关自定义客户端授权&#xff0c;实现可以为不同的接入客户端设…