传送门

显然是可以树形 $dp$ 的

对每个节点维护以下 $5$ 个东西

$1.$ 从当前节点出发往下的链的最大贡献

$2.$ 节点子树内不经过本身的路径最大贡献

$3.$ 节点子树内经过本身的路径的最大贡献

$4.$ 从当前节点出发的一条链加上经过这条链的路径构成的图形的最大贡献

$5.$ 从当前节点出发的一条链加上不经过这条链的路径构成的图形的最大贡献

然后就可以大力讨论转移,算答案的时候也同样大力讨论,细节过多,过于恶心

注意上面那些东西的贡献都只考虑在子树内,如果当前节点不是根那么对答案的贡献还要考虑父亲的那一个联通块

代码里面的转移方程有注释(这个题真是丧心病狂)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
using namespace std;
typedef long long ll;
inline int read()
{
int x=,f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
return x*f;
}
const int N=5e5+;
int T,G,n;
vector <int> V[N];
int f[N][],Ans;
inline void Max(int &x,int y) { if(y>x) x=y; }
void dfs(int x,int fa)
{
int fg= (!fa) ? : ,sz=V[x].size();
//fg 判断是否有父亲
int fr,sc,ti,fu,vfr,vsc,Lfr,Lsc,mx;
//分别是:最长链,次长链,次次长链,次次次长链,最长链从哪个儿子贡献来的,次长链从哪个儿子贡献来的
//之前所有儿子贡献的最长路径,次长路径,之前儿子内部路径的最大贡献
//为了方便区分,链就是指从x本身出发的一条路径,路径是指不一定从x出发的路径,并且这里的"长"指的是贡献大
fr=sc=ti=fu=vfr=vsc=Lfr=Lsc=mx=;
for(int i=;i<sz;i++)
{
int &v=V[x][i]; if(v==fa) continue;
dfs(v,x);
Max(f[x][], f[v][] + sz- - fg ); // 从儿子v贡献的链,sz-1是因为v本身的联通块没有贡献,-fg是不考虑父亲的贡献
Max(f[x][], max(f[v][],f[v][]) ); // 意义显然
Max(f[x][], f[v][] + sz- - fg ); // 从儿子图形的尾巴延长一个节点
Max(f[x][], f[v][] + sz- - fg ); // 从儿子图形的链往上延长一个节点
Max(f[x][], f[v][] + sz - fg ); // 从不经过儿子的路径加上x本身一个节点作为链,sz不用减1因为儿子的联通块有贡献
Max(f[x][], f[v][] + fr + sz- - fg ); // 从不经过当前儿子的路径加上之前儿子的链延长一个节点
Max(f[x][], f[v][] + sz- - fg ); // 这一行和下一行 与 上一行和上上一行差不多意思,只是路径经过了当前儿子
Max(f[x][], f[v][] + fr + sz- - fg );
Max(f[x][], f[v][] + mx + sz- - fg ); // 最后别忘了当前儿子的链加上之前儿子路径的最大贡献
if(f[v][]>=fr)
{
fu=ti, ti=sc, sc=fr, fr=f[v][];
vsc=vfr, vfr=v;
}
else if(f[v][]>=sc)
fu=ti, ti=sc, sc=f[v][], vsc=v;
else if(f[v][]>=ti) fu=ti,ti=f[v][];
else Max(fu,f[v][]);
//以上维护前4的链
int tmp=max(f[v][],f[v][]);
if(tmp>=Lfr) Lsc=Lfr,Lfr=tmp;
else Max(Lsc,tmp);
//以上维护前2的路径
Max(mx, max(f[v][],f[v][]-) );//维护mx,注意f[v][2]要减1,因为此时v本身没有贡献
}
Max(f[x][],sz-fg); /*本身一个节点作为链*/ f[x][]=f[x][]; // 显然 f[x][2] 包括 f[x][0] 的情况
Max(f[x][], fr + sc + sz- - fg ); // 当然也可以是最长链+次长链的贡献,sz-2是因为贡献最长链和次长链的儿子没有贡献联通块数量
Max(f[x][], max(f[x][],f[x][]) ); // 显然 f[x][3] 包括 f[x][0] 和 f[x][2] 的情况
Max(f[x][], fr + sc + ti + sz- - fg ); // 当前也可以是前 3 名的链的贡献
Max(Ans, Lfr + Lsc + ); // 答案可以是不相交的两条路径
Max(Ans,f[x][] + fg); Max(Ans, max(f[x][],f[x][]) + fg ); // 也要考虑 0,2,3 图形的贡献,记得+fg
Max(Ans, fr + sc + ti + fu + sz- ); // 还可以是前 4 名的链的贡献
for(int i=;i<sz;i++)
{
int &v=V[x][i],one,two;//one是不经过当前儿子的最长链,two的不经过当前儿子的最长路径
if(v==fa) continue;
if(v==vfr) one=sc,two=sc+ti;
else if(v==vsc) one=fr,two=fr+ti;
else one=fr,two=fr+sc;
Max(Ans, f[v][] + sz ); // Ans可以是儿子的路径加上 x 本身看成一条链
Max(Ans, f[v][] + one + sz- ); // 可以是儿子子树内不经过v的路径加上 x 往下的一条链
Max(Ans, f[v][] + two + sz- ); // 可以是儿子子树内不经过v路径加上经过 x 并且不经过当前儿子的路径
Max(Ans, f[v][] + one + sz- ); // 同样要考虑儿子子树内经过 v 的路径加上一些东西
Max(Ans, f[v][] + two + sz- );
Max(Ans, f[v][] + sz- ); // 也可以是儿子的 3 图形往上加上 x 本身构成的图形的贡献
Max(Ans, f[v][] + one + sz- ); // 也可以是儿子的 3 图形往上加上 x 往其他儿子的链构成的图形的贡献
Max(Ans, f[v][] + sz- ); // 也可以是儿子的 4 图形往上加上 x 本身构成的图形的贡献
Max(Ans, f[v][] + one + sz- ); // 也可以是儿子的 4 图形往上加上 x 往其他儿子的链构成的图形的贡献
}
}
inline void Clear()
{
Ans=;
for(int i=;i<=n;i++)
memset(f[i],,sizeof(f[i])),V[i].clear();
}
inline void solve()
{
n=read();
for(int i=;i<=G;i++) int a=read();
for(int i=;i<n;i++)
{
int a=read(),b=read();
V[a].push_back(b); V[b].push_back(a);
}
if(n==) printf("0\n");
else dfs(,),printf("%d\n",Ans);
}
int main()
{
T=read(); G=read()<<;
while(T--) solve(),Clear();
return ;
}

P3748 [六省联考2017]摧毁“树状图”的更多相关文章

  1. 六省联考2017 Day1

    目录 2018.3.18 Test T1 BZOJ.4868.[六省联考2017]期末考试 T2 T3 BZOJ.4870.[六省联考2017]组合数问题(DP 矩阵快速幂) 总结 考试代码 T1 T ...

  2. 洛谷 P3747 [六省联考2017]相逢是问候 解题报告

    P3747 [六省联考2017]相逢是问候 题目描述 \(\text {Informatik verbindet dich und mich.}\) 信息将你我连结. \(B\) 君希望以维护一个长度 ...

  3. 【BZOJ4873】[六省联考2017]寿司餐厅(网络流)

    [BZOJ4873][六省联考2017]寿司餐厅(网络流) 题面 BZOJ 洛谷 题解 很有意思的题目 首先看到答案的计算方法,就很明显的感觉到是一个最大权闭合子图. 然后只需要考虑怎么构图就行了. ...

  4. 【BZOJ4868】[六省联考2017]期末考试(贪心)

    [BZOJ4868][六省联考2017]期末考试(贪心) 题面 BZOJ 洛谷 题解 显然最终的答案之和最后一个公布成绩的课程相关. 枚举最后一天的日期,那么维护一下前面有多少天可以向后移,后面总共需 ...

  5. 六省联考2017 Day2

    目录 2018.3.27 Test 总结 T1 T2 T3 BZOJ.4873.[六省联考2017]寿司餐厅(最小割ISAP 最大权闭合子图) 考试代码 T1 T2 T3 2018.3.27 Test ...

  6. P3746 [六省联考2017]组合数问题

    P3746 [六省联考2017]组合数问题 \(dp_{i,j}\)表示前\(i\)个物品,取的物品模\(k\)等于\(r\),则\(dp_{i,j}=dp_{i-1,(j-1+k)\%k}+dp_{ ...

  7. [luogu] P3745 [六省联考2017]期末考试 (贪心)

    P3745 [六省联考2017]期末考试 题目描述 有 \(n\) 位同学,每位同学都参加了全部的 \(m\) 门课程的期末考试,都在焦急的等待成绩的公布. 第 \(i\) 位同学希望在第 \(t_i ...

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

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

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

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

随机推荐

  1. ARTS打卡计划第八周

    Algorithms: https://leetcode-cn.com/problems/repeated-substring-pattern/ 重复子字符串 Review:  “I’m Leavin ...

  2. csp-s模拟80(b)

    头一次中午考试,上来一看三个题目以为是三个板子,但一看数据范围就不对劲. T1: 考场上的想法是:找出循环节,对于数组一头一尾的不在循环节中的,维护出以某数结尾/开头的上升序列,对于中间的循环部分只取 ...

  3. Nginx-HTTP之框架的初始化

    http 框架的初始化与 nginx-rtmp 框架的初始化类似: Nginx-rtmp之配置项的管理 1. ngx_http_module_t ngx_http_module 核心模块定义了新的模块 ...

  4. Qt DLL总结【一】-链接库预备知识

    1.链接库概念 静态链接库和动态链接库介绍 我们可以创建一种文件里面包含了很多函数和变量的目标代码,链接的时候只要把这个文件指示给链接程序就自动地从文件中查找符合要求的函数和变量进行链接,整个查找过程 ...

  5. How to use reminder feature of the outlook

    https://support.office.com/en-us/article/set-or-remove-reminders-7a992377-ca93-4ddd-a711-851ef359792 ...

  6. article收藏

    sca https://github.com/spring-cloud-incubator/spring-cloud-alibaba spring-cloud-document https://git ...

  7. rally测试opentack------安装部署和简单实践

    1,下载 git clone git://git.openstack.org/openstack/rally 或者 git clone https://git.openstack.org/openst ...

  8. 为什么HashMap继承了AbstractMap还要实现Map?

    前言 之前看源码一直忽略了这个现象,按理说HashMap的父类AbstractMap已经实现了Map,它为什么还要实现一次呢?遂上网查了一下,背后原因让人大跌眼镜. 原因 这是类库设计者的拼写错误,其 ...

  9. iOS UIBarButtonItem 固定尺寸

    自定义UIBarButtonItem的时候发现 有时候UIBarButtonItem尺寸会发生变化 通过以下方式可以很好的解决问题 [button.widthAnchor constraintEqua ...

  10. Arrays.asList()使用指南

    简介 Arrays.asList()在平时开发中还是比较常见的,我们可以使用它将一个数组转换为一个List集合. String[] myArray = { "Apple", &qu ...