【BZOJ3743】[Coci2015]Kamp 树形DP
【BZOJ3743】[Coci2015]Kamp
Description
Input
Output
Sample Input
1 2 4
1 3 1
2 5 1
2 4 2
4 7 3
4 6 2
3
7
Sample Output
15
10
13
16
15
10
HINT
题解:我们先高出这k个点的虚树,先考虑出发点u这个点是虚树上的点,且必须返回出发点时答案是什么。显然答案就是这个虚树的所有边的长度之和*2。
那么如果要返回出发点呢?如果我们再v结束,那么答案就会减去dis(u,v),那么显然dis(u,v)越大越好,所以树形DP求一下每个点到虚树上点的距离最大值即可。
然后如果u不在虚树上呢?那么它还要先走到虚树上,所以再维护一下每个点到虚树上点的距离最小值即可。
代码还是很不可读的~
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
const int maxn=500010;
ll ans;
int to[maxn<<1],next[maxn<<1],val[maxn<<1],head[maxn],p[maxn],q[maxn],s[maxn],fa[maxn],Q[maxn],st[maxn];
ll dep[maxn],f[maxn][2],g[maxn],h[maxn][2],k[maxn];
int n,m,cnt,top,np,mp;
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
void add(int a,int b,int c)
{
to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++;
}
void dfs(int x)
{
p[x]=++p[0],Q[p[0]]=x;
for(int i=head[x];i!=-1;i=next[i]) if(to[i]!=fa[x]) dep[to[i]]=dep[x]+val[i],fa[to[i]]=x,dfs(to[i]);
q[x]=p[0];
}
int main()
{
n=rd(),m=rd();
int i,a,b,c,x,y;
ll d;
memset(head,-1,sizeof(head));
for(i=1;i<n;i++) a=rd(),b=rd(),c=rd(),add(a,b,c),add(b,a,c);
dfs(1);
np=n,mp=0;
memset(f,0xc0,sizeof(f)),memset(g,0xc0,sizeof(g)),memset(h,0x3f,sizeof(h)),memset(k,0x3f,sizeof(k));
for(i=1;i<=m;i++) x=s[i]=rd(),f[x][0]=g[x]=h[x][0]=k[x]=0,np=min(np,p[x]),mp=max(mp,p[x]);
top=1;
for(i=1;i<=n;i++) if(p[i]<=np&&q[i]>=mp&&dep[i]>=dep[top]) top=i;
for(i=n;i>=2;i--)
{
x=Q[i],y=fa[x],d=dep[x]-dep[y];
if(f[y][0]>f[x][0]+d) f[y][1]=max(f[y][1],f[x][0]+d);
else f[y][1]=f[y][0],f[y][0]=f[x][0]+d;
if(!h[x][0]&&x!=top) h[y][0]=0,ans+=(dep[x]-dep[y])<<1;
if(h[y][0]<h[x][0]+d) h[y][1]=min(h[y][1],h[x][0]+d);
else h[y][1]=h[y][0],h[y][0]=h[x][0]+d;
}
for(i=2;i<=n;i++)
{
x=Q[i],y=fa[x],d=dep[x]-dep[y],g[x]=max(g[x],g[y]+d),k[x]=min(k[x],k[y]+d);
if(f[y][0]==f[x][0]+d) g[x]=max(g[x],f[y][1]+d);
else g[x]=max(g[x],f[y][0]+d);
if(h[y][0]==h[x][0]+d) k[x]=min(k[x],h[y][1]+d);
else k[x]=min(k[x],h[y][0]+d);
}
for(i=1;i<=n;i++) printf("%lld\n",ans+2*min(k[i],h[i][0])-max(g[i],f[i][0]));
return 0;
}
【BZOJ3743】[Coci2015]Kamp 树形DP的更多相关文章
- bzoj 3743 [Coci2015]Kamp——树形dp+换根
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3743 树形dp+换根. “从根出发又回到根” 减去 “mx ” . 注意dfsx里真的要改那 ...
- bzoj3743 [Coci2015]Kamp 常州模拟赛d6t2
3743: [Coci2015]Kamp Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 484 Solved: 229[Submit][Status ...
- 『kamp 树形dp』
kamp Description jz 市的云台山是个很美丽的景区,小 x 暑期到云台山打工,他的任务是开景区的大巴. 云台山景区有 N 个景点,这 N 个景点由 N-1 条道路连接而成,我们保证这 ...
- bzoj 3743 [ Coci 2015 ] Kamp —— 树形DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3743 一开始想到了树形DP,处理一下子树中的最小值,向上的最小值,以及子树中的最长路和向上的 ...
- 2018.09.28 bzoj3743: [Coci2015]Kamp(树形dp)
传送门 这是一道很有意思的题. 我们把所有的关键点都提出来,当成一棵有边权的虚树. 然后发现虚树上除最后不回到虚根的那条路径外外每条边都会被走两遍. 显然要让答案最优,不走的路径应该在虚树的直径上,于 ...
- [bzoj3743 Coci2015] Kamp(树形dp)
传送门 Description 一颗树n个点,n-1条边,经过每条边都要花费一定的时间,任意两个点都是联通的. 有K个人(分布在K个不同的点)要集中到一个点举行聚会. 聚会结束后需要一辆车从举行聚会的 ...
- [Bzoj3743][Coci2015] Kamp【换根Dp】
Online Judge:Bzoj3743 Label:换根Dp,维护最长/次长链 题目描述 一颗树n个点,n-1条边,经过每条边都要花费一定的时间,任意两个点都是联通的. 有K个人(分布在K个不同的 ...
- BZOJ3743 COCI2015Kamp(树形dp)
设f[i]为由i开始遍历完子树内所要求的点的最短时间,g[i]为由i开始遍历完子树内所要求的点最后回到i的最短时间.则g[i]=Σ(g[j]+2),f[i]=min{g[i]-g[j]+f[j]-1} ...
- bzoj3743: [Coci2015]Kamp
首先树dp求出一个点的答案 然后再一遍dfs换根(是叫做换根吗.. 详见代码 #include <iostream> #include <cstdio> #include &l ...
随机推荐
- OpenGL投影矩阵【转】
OpenGL投影矩阵 概述 透视投影 正交投影 概述 计算机显示器是一个2D平面.OpenGL渲染的3D场景必须以2D图像方式投影到计算机屏幕上.GL_PROJECTION矩阵用于该投影变换.首先,它 ...
- 转 : SQL Server数据库优化经验总结
优化数据库的注意事项: 1.关键字段建立索引. 2.使用存储过程,它使SQL变得更加灵活和高效. 3.备份数据库和清除垃圾数据. 4.SQL语句语法的优化.(可以用Sybase的SQL Expert, ...
- CentOS 7.2安装lepus数据库监控系统
环境说明 系统版本 CentOS 7.2 x86_64 软件版本 lepus 3.7 Lepus是一套开源的数据库监控平台,目前已经支持MySQL.Oracle.SQLServer.MongoDB ...
- 初识Nginx及编译安装Nginx
初识Nginx及编译安装Nginx 环境说明: 系统版本 CentOS 6.9 x86_64 软件版本 nginx-1.12.2 1.什么是Nginx? 如果你听说或使用过Apache软件 ...
- SSO单点登录系列6:cas单点登录防止登出退出后刷新后退ticket失效报500错
这个问题之前就发现过,最近有几个哥们一直在问我这个怎么搞,我手上在做另一个项目,cas就暂时搁浅了几周.现在我们来一起改一下你的应用(client2/3)的web.xml来解决这个2b问题,首先看下错 ...
- Java基础学习过程
转载:http://blog.csdn.net/scythe666/article/details/51699954JVM 1. 内存模型( 内存分为几部分? 堆溢出.栈溢出原因及实例?线上如何排查? ...
- redis学习笔记——入门
基本安装和用法:http://www.tuicool.com/articles/QzMRNb Redis如何通过本机客户端访问远程服务器段:http://blog.sina.com.cn/s/blog ...
- Java中的回调函数学习-深入浅出
Java中的回调函数一般来说分为下面几步: 声明回调函数的统一接口interface A.包括方法callback(); 在调用类caller内将该接口设置为私有成员private A XXX; 在c ...
- MSSQL注入SA权限不显错模式下的 入 侵
一般新手扫到不显错的SA(systemadmin)的注入点时,虽然工具能猜表列目录但还是很麻烦有的人就直接放弃了,今天我给大家演示下如何利用.方法很简单大家看操作. 我这里使用的是 火狐的插件提交参数 ...
- Android学习(十一) File文件操作
File类 1.获取当前应用程序的目录: this.getFilesDir(); //获取当前应用程序的数据目录 ...