首先只要得到 \(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. 西门子PLC与上位机通信方案梳理

    一.前言 大家好!我是付工. 西门子PLC是工控领域使用非常多的一种PLC品牌,对于上位机开发人员来说,对于西门子PLC的通信,我们一般可以采取哪些通信方式呢? 今天跟大家分享一下上位机实现与西门子P ...

  2. Java基础面试:Java中的方法

    Java 中的方法 什么是方法 方法是 Java 中的一段可重用的代码块,用于执行特定的任务,是程序中的最小执行单元. 参数:方法可以接受一个或多个参数,这些参数是传递给方法的值,用于方法内部的逻辑运 ...

  3. c++死锁调试 ,gdb pstack

    psatck ‌pstack命令‌是一个在Linux系统中用于查看进程堆栈信息的工具. 写了一个服务端死锁程序,如下: #include <iostream> #include <t ...

  4. Qt通用方法及类库2

    函数名 //初始化数据库 static void initDb(const QString &dbName); //初始化文件,不存在则拷贝 static void initFile(cons ...

  5. 多语言越狱很棒!😊MULTILINGUAL JAILBREAK CHALLENGES IN🧜‍♀️LARGE LANGUAGE MODELS

    写这篇的时候第一次认识到了附录内容的重要性(bushi只是这篇读了全部的附录),它可以让你明确文章全部的实验,并且其中包含很多辅助你对正文理解的表格 禁止盗用,侵权必究!!!欢迎大家积极举报

  6. VisualSFM的配置与使用 & MeshLab的网格生成与纹理添加

    VisualSFM的配置与使用 & MeshLab的网格生成与纹理添加 翻译 搜索 复制

  7. Vue.js 监听属性的使用

    示例源码: <div id = "computed_props"> 千米 : <input type = "text" v-model = & ...

  8. Linux安装配置Go语言

    Linux安装配置Go语言 官网:https://go.dev/dl/ 从官网下载,选择linux下载压缩包. sudo cp -r go/ /usr/local sudo gedit /etc/pr ...

  9. DVWA靶场Insecure CAPTCHA(不安全验证)漏洞所有级别通关教程及源码审计

    Insecure CAPTCHA(不安全验证) Insecure CAPTCHA(不安全验证)漏洞指的是在实现 CAPTCHA(完全自动化公共图灵测试区分计算机和人类)机制时,未能有效保护用户输入的验 ...

  10. C Primer Plus 第6版 第三章 编程练习参考答案

    编译环境VS Code+WSL GCC 源码在文末下载 /*第1题*************************/ #include<stdio.h> int main() { int ...