题目

给定一棵树,边权是整数 \(c_i\) ,找出两条不相交的链(没有公共点),

使得链长的乘积最大(链长定义为这条链上所有边的权值之和,如果这条链只有1个点则链长视为0)。

\(n\leq 4*10^5,|c_i|\leq 10^9\)


分析

首先考虑一条直径就是维护最大值和次大值,

然后换根就可以得到经过任意一点的直径 \(f[x]\)。

但是两条直径还要考虑不相交,那么分类讨论一下。

如果直径处在两个不同的子树内,可以提前处理 \(dp[x]\) 表示 \(x\) 的子树内 \(f[x]\) 的最大值。

对于 \(x\),求出 \(\max\{dp[y]*dp[y']\}\) 即可

否则,直径一定可以被表示成一条经过 \(x\) 且不经过 \(y\),一条在以 \(y\) 为根的子树内,也就是 \(dp[y]\)

\(x\) 这部分挺难求的,任意一点直径却并没有保证它不经过 \(y\),所以还要维护第三大值,剔除掉 \(y\) 的贡献,再贡献给 \(y\)

最后如果要卡常,就只在答案这里开 __int128 就可以了。

心路历程:提交了16次,一开始根本没发现可以处在两个不同的子树内,而且对求第三大值犹豫再三。

而且调题真的很难受,没求处在两个不同的子树内的时候,只有一个点是RE的(玄学,令根为 \(\left\lceil\frac{n}{2}\right\rceil\) 就会少点RE)

但是其实调题的时候做法还不够完整,因为这么做,我第五个点是WA的,接着就一直查错,然后发现了这种情况,一开始想复杂了,后来利用 \(\max\{dp[y]*dp[y']\}\) 就可以了


代码

#include <cstdio>
#include <cctype>
using namespace std;
const int N=400011; typedef long long lll;
struct node{int y,w,next;}e[N<<1]; __int128 ans;
lll Mn[N],Mx[N],mn[N][3],mx[N][3]; int et=1,as[N],n;
int iut(){
int ans=0,f=1; char c=getchar();
while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans*f;
}
void print(__int128 ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
void Max(lll &a,lll b){a=a>b?a:b;}
void Min(lll &a,lll b){a=a<b?a:b;}
__int128 max(__int128 a,__int128 b){return a>b?a:b;}
void dfs1(int x,int fa){
for (int i=as[x],flag;i;i=e[i].next)
if (e[i].y!=fa){
dfs1(e[i].y,x);
flag=1;
for (int k=0;k<3&&flag;++k)
for (int j=k;j<3&&flag;++j)
if (mn[x][j]>mn[e[i].y][k]+e[i].w){
for (int _j=2;_j>j;--_j) mn[x][_j]=mn[x][_j-1];
mn[x][j]=mn[e[i].y][k]+e[i].w,flag=0;
}
flag=1;
for (int k=0;k<3&&flag;++k)
for (int j=k;j<3&&flag;++j)
if (mx[x][j]<mx[e[i].y][k]+e[i].w){
for (int _j=2;_j>j;--_j) mx[x][_j]=mx[x][_j-1];
mx[x][j]=mx[e[i].y][k]+e[i].w,flag=0;
}
ans=max(ans,(__int128)Mn[x]*Mn[e[i].y]);
ans=max(ans,(__int128)Mx[x]*Mx[e[i].y]);
Min(Mn[x],Mn[e[i].y]),Max(Mx[x],Mx[e[i].y]);
}
Min(Mn[x],mn[x][0]+mn[x][1]);
Max(Mx[x],mx[x][0]+mx[x][1]);
}
void dfs2(int x,int fa){
lll MN[3],MX[3];
for (int i=0;i<3;++i) MN[i]=mn[x][i],MX[i]=mx[x][i];
for (int i=as[x],flag;i;i=e[i].next)
if (e[i].y!=fa){
for (int j=0;j<3;++j) mn[x][j]=MN[j],mx[x][j]=MX[j];
flag=1;
for (int k=0;k<3&&flag;++k)
for (int j=k;j<3&&flag;++j)
if (mn[x][j]==mn[e[i].y][k]+e[i].w){
for (int _j=j;_j<2;++_j) mn[x][_j]=mn[x][_j+1];
mn[x][2]=flag=0;
}
flag=1;
for (int k=0;k<3&&flag;++k)
for (int j=k;j<3&&flag;++j)
if (mx[x][j]==mx[e[i].y][k]+e[i].w){
for (int _j=j;_j<2;++_j) mx[x][_j]=mx[x][_j+1];
mx[x][2]=flag=0;
}
flag=1;
for (int k=0;k<3&&flag;++k)
for (int j=k;j<3&&flag;++j)
if (mn[e[i].y][j]>mn[x][k]+e[i].w){
for (int _j=2;_j>j;--_j) mn[e[i].y][_j]=mn[e[i].y][_j-1];
mn[e[i].y][j]=mn[x][k]+e[i].w,flag=0;
}
flag=1;
for (int k=0;k<3&&flag;++k)
for (int j=k;j<3&&flag;++j)
if (mx[e[i].y][j]<mx[x][k]+e[i].w){
for (int _j=2;_j>j;--_j) mx[e[i].y][_j]=mx[e[i].y][_j-1];
mx[e[i].y][j]=mx[x][k]+e[i].w,flag=0;
}
ans=max(ans,(__int128)Mn[e[i].y]*(mn[x][0]+mn[x][1]));
ans=max(ans,(__int128)Mx[e[i].y]*(mx[x][0]+mx[x][1]));
dfs2(e[i].y,x);
}
}
int main(){
n=iut();
for (int i=1;i<n;++i){
int x=iut(),y=iut(),w=iut();
e[++et]=(node){y,w,as[x]},as[x]=et;
e[++et]=(node){x,w,as[y]},as[y]=et;
}
dfs1((n+1)>>1,0),dfs2((n+1)>>1,0);
print(ans);
return 0;
}

#树形dp,直径#51nod 1812 树的双直径的更多相关文章

  1. 51nod 1812 树的双直径 题解【树形DP】【贪心】

    老了-稍微麻烦一点的树形DP都想不到了. 题目描述 给定一棵树,边权是整数 \(c_i\) ,找出两条不相交的链(没有公共点),使得链长的乘积最大(链长定义为这条链上所有边的权值之和,如果这条链只有 ...

  2. 51nod1812树的双直径(换根树DP)

    传送门:http://www.51nod.com/Challenge/Problem.html#!#problemId=1812 题解:头一次写换根树DP. 求两条不相交的直径乘积最大,所以可以这样考 ...

  3. LOJ2250 [ZJOI2017] 仙人掌【树形DP】【DFS树】

    题目分析: 不难注意到仙人掌边可以删掉.在森林中考虑树形DP. 题目中说边不能重复,但我们可以在结束后没覆盖的边覆盖一个重复边,不改变方案数. 接着将所有的边接到当前点,然后每两个方案可以任意拼接.然 ...

  4. hdu6035 Colorful Tree 树形dp 给定一棵树,每个节点有一个颜色值。定义每条路径的值为经过的节点的不同颜色数。求所有路径的值和。

    /** 题目:hdu6035 Colorful Tree 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6035 题意:给定一棵树,每个节点有一个颜色值.定 ...

  5. 51nod"省选"模测 A 树的双直径(树形dp)

    题意 题目链接 Sol 比赛结束后才调出来..不多说啥了,就是因为自己菜. 裸的up-down dp,维护一下一个点上下的直径就行,一开始还想了个假的思路写了半天.. 转移都在代码注释里 毒瘤题目卡空 ...

  6. hdu 2196(方法1:经典树形DP+方法2:树的直径)

    Computer Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  7. 【洛谷】2607: [ZJOI2008]骑士【树形DP】【基环树】

    P2607 [ZJOI2008]骑士 题目描述 Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬. 最近发生了一件可怕的事情,邪恶的Y国发动了一 ...

  8. HDU4612(Warm up)2013多校2-图的边双连通问题(Tarjan算法+树形DP)

    /** 题目大意: 给你一个无向连通图,问加上一条边后得到的图的最少的割边数; 算法思想: 图的边双连通Tarjan算法+树形DP; 即通过Tarjan算法对边双连通缩图,构成一棵树,然后用树形DP求 ...

  9. 【BZOJ-2286】消耗战 虚树 + 树形DP

    2286: [Sdoi2011消耗战 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2120  Solved: 752[Submit][Status] ...

  10. BZOJ5287 HNOI2018毒瘤(虚树+树形dp)

    显然的做法是暴力枚举非树边所连接两点的选或不选,大力dp.考场上写的是最暴力的O(3n-mn),成功比大众分少10分.容斥或者注意到某些枚举是不必要的就能让底数变成2.但暴力的极限也就到此为止. 每次 ...

随机推荐

  1. TCP/IP的确认号,序列号和超时重传的学习笔记

    一:确认应答和序列号 在tcp中,发送端的数据到达主机时,接收端会返回一个已收到的通知.这个消息叫做确认应答(ACK). 当发送端发送数据后,会等待对端的确认应答.如果有确认应答,说明数据已经成功到达 ...

  2. [Revit二次开发] 使用过滤器时,可能存在的坑:FilteredElementCollector.MoveNext()报错

    1.问题描述 在使用FilteredElementCollector时,如果涉及到需要对collector进行多次过滤处理,可能会出现MoveNext的报错. 问题代码如下: 1 var collec ...

  3. 使用`react-hooks写法`对`antd的Upload.Dragger上传组件`进行二次封装

    使用react-hooks写法对antd的Upload.Dragger上传组件进行二次封装 预期 对antd的Upload.Dragger组件进行二次封装,让它的使用方法和Upload.Dragger ...

  4. Kotlin 基础入门

    目录 一.基础语法 1.1 常见数据类型 1.2 变量 1.2.1 变量声明 1.2.2 类型推断 1.2.3 Null 安全 1.2.4 面向对象语言 1.3 流程控制 1.3.1 if 表达式 1 ...

  5. 名校AI课推荐 | MIT6.S191《深度学习导论》

    "连续开设5年,对新手友好.易于上手,参加课程的多数学生来自非计算机科学领域--" 推荐一门AI课程--MIT官方深度学习入门课程6.S191<深度学习导论(2022)> ...

  6. Vue 之 new vue({})与export default {} 的区别

    刚入门 vue 的,可能会有这样的困惑:什么时候用new vue({}),什么时候用export default {} 呢? 比如,我们在用 cli 创建项目时 在 main.js 入口里面用的时ne ...

  7. 【Azure App Service】当App Service中使用系统标识无法获取Access Token时

    问题描述 App Serive上的应用配置了系统标识(System Identity),通过系统标识获取到访问Key Vault资源的Access Token.但这次确遇见了无法获取到正常的Acces ...

  8. 【Azure 云服务】查看Azure云服务在中国区域的VM型号大小列表(型号编码,定价层,以及CPU, Memory等)

    问题描述 如何查看创建 Azure Cloud Service 服务时,可以选择的VM型号吗? 问题解答 根据官网参考,可以通过PowerShell脚本 Get-AzComputeResourceSk ...

  9. 【Azure 应用程序见解】通过Azure Funciton的门户启用Application Insights后,Application Insights无法收到监控数据

    问题描述 比较早期创建的Azure Funciton服务,近期发现在门户中已经启用了Application Insights功能,但是正确配置Applicaiton Insights后,却无法获取关联 ...

  10. Java 接口的应用:代理模式

    1 package com.bytezreo.interfacetest; 2 3 /** 4 * 5 * @Description 接口的应用:代理模式 6 * @author Bytezero·z ...