首先只要得到 \(x=0\) 时的答案,就可以 \(AC\) 本题。这是很重要的。

考虑由于不能有重复经过的边,所以两路径交点数量 \(\le 1\)。

容易想到设 \(dp_u\) 表示以 \(u\) 为端点的链中的贡献最大值。考虑换根 \(dp\),所以先设它只表示它子树内的部分。

当交点数量 \(=1\) 时,显然可以理解为从一个节点出发的 \(0-4\) 条链,要这些链产生的贡献最大,所以要维护每个点的前四大链,这里的大指 \(dp\) 值大。

当交点数量 \(=0\) 时,可以看作是子树内有一条链,子树外有一条链的情况。

那么首先必须要维护前四大链 \(mx_{x,0/1/2/3}\)。

其次由于删掉一个点会产生儿子 \(+1\) 那么多个联通块,所以还要维护儿子数量 \(cnt_i\)。

考虑到子树内有一条链也得维护,所以得维护 \(f_i\) 表示过子树根的路径最大贡献,\(g_i\) 表示不一定过子树根的路径最大贡献。

由于 \(g_i\) 不好维护,所以再设 \(d_i\) 表示我们认为删掉 \(i\) 后 \(i\) 外还有联通块时,路径的最大贡献。那么就有:

\[\begin{cases}
dp_x=cnt_i+\max(0,mx_{x,0}-1)\\
f_x=\max(dp_x,mx_{x,0}+mx_{x,1}+cnt_x-2)\\
g_x=\max(\max\limits_{y\in sn_x}d_y,f_x)\\
d_x=\max(\max\limits_{y\in sn_x}d_y,f_x+1)
\end{cases}
\]

\(\max\limits_{y\in sn_x}d_y\) 可以通过预处理得到。换根时式子相同,所有定义中“子树内”全部改为“以该点为根的树”即可。

时间复杂度 \(O(tn)\)。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,ans,mx[N][5],fmx[N][3];
int t,id,f[N],dp[N],g[N],d[N];
vector<int>ve[N];
void add(int x,int v){
mx[x][4]=v;
for(int i=3;~i;i--)
if(mx[x][i+1]>mx[x][i])
swap(mx[x][i+1],mx[x][i]);
}void adf(int x,int v){
fmx[x][2]=v;
for(int i=1;~i;i--)
if(fmx[x][i+1]>fmx[x][i])
swap(fmx[x][i+1],fmx[x][i]);
}void dfs1(int x,int fa){
int cnt=ve[x].size()-1;
for(auto y:ve[x]) if(y!=fa)
dfs1(y,x),add(x,dp[y]),adf(x,d[y]);
dp[x]=cnt+max(1,mx[x][0])-1;
f[x]=max(dp[x],mx[x][0]+mx[x][1]+cnt-2);
g[x]=max(fmx[x][0],f[x]);
d[x]=max(fmx[x][0],f[x]+1);
}void dfs2(int x,int fa){
int sz=ve[x].size(),cnt=sz-1;
for(int i=0;i<5;i++)
ans=max(ans,sz),sz+=mx[x][i]-1;
for(auto y:ve[x]){
if(y==fa) continue;
int mo=mx[x][0]+mx[x][1];
int mz=mx[x][0],mt=fmx[x][0];
if(dp[y]==mx[x][0])
mo+=mx[x][2]-mz,mz=mx[x][1];
if(dp[y]==mx[x][1]) mo=mz+mx[x][2];
if(fmx[x][0]==d[y]) mt=fmx[x][1];
dp[x]=cnt+max(1,mz)-1;
f[x]=max(dp[x],mo+cnt-2),add(y,dp[x]);
g[x]=max(mt,f[x]),d[x]=max(mt,f[x]+1);
adf(y,d[x]),ans=max(ans,g[x]+f[y]),dfs2(y,x);
}
}void solve(){
for(int i=1;i<=n;i++){
ve[i].clear(),g[i]=d[i]=f[i]=dp[i]=0;
mx[i][0]=mx[i][1]=mx[i][2]=mx[i][3]=0;
fmx[i][0]=fmx[i][1]=0;
}cin>>n;int tmp;
for(int i=0;i<id*2;i++) cin>>tmp;
for(int i=1,x,y;i<n;i++)
cin>>x>>y,ve[x].push_back(y),ve[y].push_back(x);
ans=0,dfs1(1,0),dfs2(1,0),cout<<ans<<"\n";
}int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>t>>id;
while(t--) solve();
return 0;
}

[SHOI2017] 摧毁“树状图”的更多相关文章

  1. bzoj 4871: [Shoi2017]摧毁“树状图” [树形DP]

    4871: [Shoi2017]摧毁"树状图" 题意:一颗无向树,选两条边不重复的路径,删去选择的点和路径剩下一些cc,求最多cc数. update 5.1 : 刚刚发现bzoj上 ...

  2. bzoj 4871: [Shoi2017]摧毁“树状图”

    4871: [Shoi2017]摧毁“树状图” Time Limit: 25 Sec  Memory Limit: 512 MBSubmit: 53  Solved: 9[Submit][Status ...

  3. BZOJ4871 Shoi2017摧毁“树状图”(树形dp)

    设f[i][0/1/2/3/4/5]表示i子树中选一条链不包含根/i子树中选一条链包含根但不能继续向上延伸/i子树中选一条链可以继续向上延伸/选两条链不包含根/选两条链包含根但不能继续向上延伸/选两条 ...

  4. bzoj 4871: [Shoi2017]摧毁“树状图”【树形dp】

    做不来--参考https://www.cnblogs.com/ezyzy/p/6784872.html #include<iostream> #include<cstdio> ...

  5. bzoj4871 [Heoi2017]摧毁“树状图”

    刷完了去年的省选题,发现自己dp已经凉凉了. 虽然暴力可以拿到80分的好成绩,但是正解的dp状态和转移还是没能想到,是时候补一波dp了 这道题我们肯定是要树形dp,存的肯定就是子树某种状态的最多的联通 ...

  6. P3748 [六省联考2017]摧毁“树状图”

    传送门 显然是可以树形 $dp$ 的 对每个节点维护以下 $5$ 个东西 $1.$ 从当前节点出发往下的链的最大贡献 $2.$ 节点子树内不经过本身的路径最大贡献 $3.$ 节点子树内经过本身的路径的 ...

  7. SqlServer-无限递归树状图结构设计和查询

    在现实生活中,公司的部门设计会涉及到很多子部门,然后子部门下面又存在子部门,形成类似判断的树状结构,比如说评论楼中楼的评论树状图,职位管理的树状图结构等等,实现类似的树状图数据结构是在开发中经常出现的 ...

  8. Android开源图表之树状图和饼状图的官方示例的整理

    最近由于工作需要,所以就在github上搜了下关于chart的三方框架 官方地址https://github.com/PhilJay/MPAndroidChart 由于工作需要我这里整理了一份Ecli ...

  9. D3树状图给指定特性的边特别显示颜色

    D3作为前端图形显示的利器,功能之强,对底层技术细节要求相对比较多. 有一点,就是要理解其基本的数据和节点的匹配规则架构,即enter,update和exit原理,我前面的D3基础篇中有介绍过,不明白 ...

  10. D3树状图异步按需加载数据

    D3.js这个绘图工具,功能强大不必多说,完全一个Data Driven Document的绘图工具,用户可以按照自己的数据以及希望实现的图形,随心所欲的绘图. 图形绘制,D3默认采用的是异步加载,但 ...

随机推荐

  1. pdf.js 笔记

    1.介绍 官方文档,pdf.js是由mozilla开源的js库,用于在web环境中渲染和显示pdf文档 目前,绝大多数PC浏览器都已经内置了pdf阅读器,能够直接预览pdf文件(内置了pdf.js), ...

  2. Winform多线程持续读取PLC数据

    1.Winform窗体界面 2.后台代码 点击查看代码 using Modbus.Device; using System; using System.Collections.Generic; usi ...

  3. 腾讯云 COS 多 AZ 存储保证服务高可用性

    腾讯云 COS 的多 AZ 存储架构能够为用户数据提供数据中心级别的容灾能力.多 AZ 存储将客户数据分散存储在城市中多个不同的数据中心,当某个数据中心因为自然灾害.断电等极端情况导致整体故障时,多 ...

  4. IOS多线程之NSOperation(2)

    IOS多线程之NSOperation(2) 最大并发数 open var maxConcurrentOperationCount: Int 并发数就是同时执行的任务数.比如,同时开3个线程执行3个任务 ...

  5. 金TECH频道|最近备受关注的“应用重构”到底是什么?

    "金TECH频道"旨在为您分享中电金信助力行业数字化转型的最新产品业务动态.技术观点洞察与应用实践案例.让我们在这里,与行业发展同频共振,共筑数字新基石.

  6. 【人工智能】【Python】Numpy基础

    Numpy 目录 Numpy Numpy简介 ndarray与原生Python List运算效率对比 N阶数组 ndarray (1)创建数组 (2)生成数组 生成纯1数组 生成纯0数组 从现有数组生 ...

  7. sudo kill -HUP 10146

    systemctl status docker   systemctl reload docker

  8. Qt编写地图综合应用56-实时动态轨迹

    一.前言 实时动态轨迹经历过很多个版本的迭代,此功能最初是一个客户定制的,主要是需要在地图上动态显示GPS的运动轨迹,有个应用场景就是一个带有监控的车子,实时在运动中,后台可以接收到经纬度信息,需要绘 ...

  9. 《Spring MVC+MyBatis快速开发与项目实战》-黄文毅2019:一书的源码和配套视频下载地址

    <Spring MVC+MyBatis快速开发与项目实战>-黄文毅2019:一书的源码下载地址: http://github.com/huangwenyi10/springmvc-myba ...

  10. IM扫码登录技术专题(三):通俗易懂,IM扫码登录功能详细原理一篇就够

    本文引用了作者"大古同学"的"二维码扫码登录是什么原理"一文的主要内容,为了更好的理解和阅读,即时通讯网收录时有修订和改动,感谢原作者的分享. 1.引言 自从微 ...