P3748 [六省联考2017]摧毁“树状图”
显然是可以树形 $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]摧毁“树状图”的更多相关文章
- 六省联考2017 Day1
目录 2018.3.18 Test T1 BZOJ.4868.[六省联考2017]期末考试 T2 T3 BZOJ.4870.[六省联考2017]组合数问题(DP 矩阵快速幂) 总结 考试代码 T1 T ...
- 洛谷 P3747 [六省联考2017]相逢是问候 解题报告
P3747 [六省联考2017]相逢是问候 题目描述 \(\text {Informatik verbindet dich und mich.}\) 信息将你我连结. \(B\) 君希望以维护一个长度 ...
- 【BZOJ4873】[六省联考2017]寿司餐厅(网络流)
[BZOJ4873][六省联考2017]寿司餐厅(网络流) 题面 BZOJ 洛谷 题解 很有意思的题目 首先看到答案的计算方法,就很明显的感觉到是一个最大权闭合子图. 然后只需要考虑怎么构图就行了. ...
- 【BZOJ4868】[六省联考2017]期末考试(贪心)
[BZOJ4868][六省联考2017]期末考试(贪心) 题面 BZOJ 洛谷 题解 显然最终的答案之和最后一个公布成绩的课程相关. 枚举最后一天的日期,那么维护一下前面有多少天可以向后移,后面总共需 ...
- 六省联考2017 Day2
目录 2018.3.27 Test 总结 T1 T2 T3 BZOJ.4873.[六省联考2017]寿司餐厅(最小割ISAP 最大权闭合子图) 考试代码 T1 T2 T3 2018.3.27 Test ...
- P3746 [六省联考2017]组合数问题
P3746 [六省联考2017]组合数问题 \(dp_{i,j}\)表示前\(i\)个物品,取的物品模\(k\)等于\(r\),则\(dp_{i,j}=dp_{i-1,(j-1+k)\%k}+dp_{ ...
- [luogu] P3745 [六省联考2017]期末考试 (贪心)
P3745 [六省联考2017]期末考试 题目描述 有 \(n\) 位同学,每位同学都参加了全部的 \(m\) 门课程的期末考试,都在焦急的等待成绩的公布. 第 \(i\) 位同学希望在第 \(t_i ...
- bzoj 4871: [Shoi2017]摧毁“树状图” [树形DP]
4871: [Shoi2017]摧毁"树状图" 题意:一颗无向树,选两条边不重复的路径,删去选择的点和路径剩下一些cc,求最多cc数. update 5.1 : 刚刚发现bzoj上 ...
- bzoj 4871: [Shoi2017]摧毁“树状图”
4871: [Shoi2017]摧毁“树状图” Time Limit: 25 Sec Memory Limit: 512 MBSubmit: 53 Solved: 9[Submit][Status ...
随机推荐
- Golang 函数耗时统计
当时候需要去计算一段代码或一个程序所消耗时间的时候,就需要进行统计时间,用程序去计算某一段代码的执行所需要的时间远比用眼睛直接去看程序运行时间高很多. go语言中的time包中提供了函数来提供计算消耗 ...
- Nginx之进程间的通信机制(共享内存、原子操作)
1. 概述 Linux 提供了多种进程间传递消息的方式,如共享内存.套接字.管道.消息队列.信号等,而 Nginx 框架使用了 3 种传递消息的传递方式:共享内存.套接字.信号. 在进程间访问共享资源 ...
- 项目中遇到的关于Java的问题
1.Collections对List集合中的数据进行排序 http://blog.csdn.net/veryisjava/article/details/51675036 2.Java随机数 http ...
- Error, DNGuard Runtime library not loaded!
// Token: 0x06008CE9 RID: 36073 RVA: 0x0059629A File Offset: 0x00591E9A [MethodImpl(MethodImp ...
- RunHelper,一个为跑步而设计的开源的android app
RunHelper是一个为跑步而设计的android应用,意在为爱跑步的人提供一个简洁.实用.免费的工具. 我自己也经常跑步,也用过像Nike running.runkeeper之类的app:Nike ...
- 1.springboot内置tomcat的connection相关
最近在研究tomcat的连接超时问题,环境:jdk1.8 + springboot 2.1.1.RELEASE,以下仅为个人理解,如果异议,欢迎指正. springboot的tomcat的几个配置参数 ...
- 如何向一个Fragment传递参数---setArguments方法的介绍
在我们平常开发中经常会用到Fragment,当我们使用Fragment时一般是通过new Fragment的构造方法来实现,如果我问你怎么向一个Fragment传递参数,你是不是会首先想到通过构造方法 ...
- python写入csv方法总结
最常用的一种方法,利用pandas包 import pandas as pd #任意的多组列表 a = [1,2,3] b = [4,5,6] #字典中的key值即为csv中列名 dataframe ...
- Elasticsearch.Net API 图片汇总
- python代码中判断版本
在python代码中判断python版本: if sys.version_info < (3, 0): lib.make_flows.argtypes = [c_char_p, c_char_p ...