P4383 [八省联考 2018] 林克卡特树
P4383 [八省联考 2018] 林克卡特树
米奇妙妙题
题目的主要操作就是断掉一条边再连一条边权为
我们考虑先不连那些后来加上的边权为
接下来的任务就是把所有的连通块连接在一起,可以发现,使得答案最大的连接法就是找出每个连通块中的直径后将所有块的直径依次相连,最后的答案就是所有块的直径的长度之和
现在我们就完成了问题的转化,那么现在我们要求的就是把原树分成
那么设
形式化的表达就是
证明:
对于第一种表示方法,可以理解为从
的方案一步步改成了 ,那么显然改的边越多,答案越劣 对于第二种表示方法,可以理解为从
的方案改成 ,再从 改成 ,既然 表示的是最优解,那么肯定从 改成 时会选择最优的方案,从 改成 只能选剩下的方案中最优的方案,也就是说肯定不会优于从 改成
那么我们就可以使用
因为我们计算的是每个连通块里的直径,也就是说对于这条直径中的点,它们的度数(指与直径中有多少个点相连)只有待与父亲相连的点
和不会再与父亲相连的点
,所以稍微整理下这两种东西,我们就可以得出
^
状的直径的那个转折点,事实上
要注意的是因为我们现在在使用
那么转移有:
for(int i=1;i<=n;++i) dp[i][0]=dp[i][1]={0,0},dp[i][2]={-mid,1};//初始化
for(int i=head[x],y;i;i=tree[i].nxt) if((y=tree[i].v)!=fa){
dfs(y,x);
dp[x][2]=max(dp[x][2]+dp[y][0],dp[x][1]+dp[y][1]+make_pair(tree[i].val-mid,1)),
dp[x][1]=max(dp[x][1]+dp[y][0],dp[x][0]+dp[y][1]+make_pair(1ll*tree[i].val,0)),
dp[x][0]=dp[x][0]+dp[y][0];
}
dp[x][0]=max(dp[x][0],max(dp[x][1]+make_pair(-mid,1),dp[x][2]));
这里就可以比较直观的感受定义了
因为
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=3e5+5;
const ll INF=1e18;
int n,k;
int head[N],cntt;
struct node{
int nxt,v,val;
}tree[N<<1];
void add(int u,int v,int val){
tree[++cntt]={head[u],v,val},head[u]=cntt;
tree[++cntt]={head[v],u,val},head[v]=cntt;
}
ll l,r,mid;
pair<ll,int> dp[N][3];
pair<ll,int> operator + (pair<ll,int> a,pair<ll,int> b){ return {a.first+b.first,a.second+b.second}; }
void dfs(int x,int fa){
for(int i=head[x],y;i;i=tree[i].nxt) if((y=tree[i].v)!=fa){
dfs(y,x);
dp[x][2]=max(dp[x][2]+dp[y][0],dp[x][1]+dp[y][1]+make_pair(tree[i].val-mid,1)),dp[x][1]=max(dp[x][1]+dp[y][0],dp[x][0]+dp[y][1]+make_pair(1ll*tree[i].val,0)),dp[x][0]=dp[x][0]+dp[y][0];
}
dp[x][0]=max(dp[x][0],max(dp[x][1]+make_pair(-mid,1),dp[x][2]));
}
int get(){
for(int i=1;i<=n;++i) dp[i][0]=dp[i][1]={0,0},dp[i][2]={-mid,1};
dfs(1,0);
return max(dp[1][0],max(dp[1][1],dp[1][2])).second;
}
int main(){
scanf("%d%d",&n,&k),++k;
for(int i=1,u,v,w;i<n;++i) scanf("%d%d%d",&u,&v,&w),add(u,v,w),r+=abs(w);
l=-r;
while(l<r){
mid=l+r+1>>1;
if(get()>=k) l=mid;
else r=mid-1;
}
mid=l,get(),printf("%lld",l*k+dp[1][0].first);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?