[bzoj3743 Coci2015] Kamp(树形dp)
Description
一颗树n个点,n-1条边,经过每条边都要花费一定的时间,任意两个点都是联通的。
有K个人(分布在K个不同的点)要集中到一个点举行聚会。
聚会结束后需要一辆车从举行聚会的这点出发,把这K个人分别送回去。
请你回答,对于i=1~n,如果在第i个点举行聚会,司机最少需要多少时间把K个人都送回家。
Input
第一行两个数,n,K。
接下来n-1行,每行三个数,x,y,z表示x到y之间有一条需要花费z时间的边。
接下来K行,每行一个数,表示K个人的分布。
Output
输出n个数,第i行的数表示:如果在第i个点举行聚会,司机需要的最少时间。
Sample Input
7 2
1 2 4
1 3 1
2 5 1
2 4 2
4 7 3
4 6 2
3
7
Sample Output
11
15
10
13
16
15
10
HINT
【数据规模】
K <= N <= 500000
1 <= x,y <= N, 1 <= z <= 1000000
Solution
总体上是用全部的路程减去最大的一条路程
先两次dfs求出每个点全部路程
再两次dfs求出最大一条路径
Code
//By Menteur_Hxy
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M(a,b) memset(a,(b),sizeof(a))
#define F(i,a,b) for(register int i=(a);i<=(b);i++)
#define E(i,u) for(register int i=head[u];i;i=nxt[i])
using namespace std;
typedef long long LL;
int read() {
int x=0,f=1; char c=getchar();
while(!isdigit(c)) {if(c=='-')f=-f; c=getchar();}
while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
return x*f;
}
const int N=500010;
const LL INF=0x7fffffffffffffff;
int n,k,cnt;
int nxt[N<<1],to[N<<1],w[N<<1],head[N],siz[N];
LL dis[N],down[N][2],up[N];
void dfs1(int u,int pre) { //向下
E(i,u) { int v=to[i];
if(v==pre) continue;
dfs1(v,u); siz[u]+=siz[v];
dis[u]+=dis[v]+(siz[v]?w[i]:0);
}
}
void dfs2(int u,int pre) { //向上
E(i,u) { int v=to[i];
if(v==pre) continue;
dis[v]=dis[u];
// if(siz[v])dis[v]-=w[i];
// if(siz[v]<k)dis[v]+=w[i];
if(siz[v]==k) dis[v]-=w[i];
else if(!siz[v]) dis[v]+=w[i];
dfs2(v,u);
}
}
void dfs3(int u,int pre) { //向下
down[u][0]=down[u][1]=(siz[u]?0:-INF);
E(i,u) { int v=to[i];
if(v==pre) continue;
dfs3(v,u);
if(down[v][0]+w[i]>down[u][0]) down[u][1]=down[u][0],down[u][0]=down[v][0]+w[i];
else if(down[v][0]+w[i]>down[u][1]) down[u][1]=down[v][0]+w[i];
}
}
void dfs4(int u,int pre) { //向上
E(i,u) { int v=to[i];
if(v==pre) continue;
if(down[v][0]+w[i]==down[u][0]) up[v]=down[u][1]+w[i];
else up[v]=down[u][0]+w[i];
up[v]=max(up[v],up[u]+w[i]);
dfs4(v,u);
}
}
#define add(a,b,c) nxt[++cnt]=head[a],to[cnt]=b,w[cnt]=c,head[a]=cnt
int main() {
n=read(),k=read();
F(i,1,n-1) {
int a=read(),b=read(),c=read();
add(a,b,c),add(b,a,c);
}
F(i,1,k) siz[read()]=1;
dfs1(1,0); dfs2(1,0); dfs3(1,0);
up[1]=(siz[1]?0:-INF); dfs4(1,0);
// F(i,1,n) printf("%lld ",2*dis[i]);cout<<endl;
F(i,1,n) printf("%lld\n",2*dis[i]-max(up[i],down[i][0]));
return 0;
}
[bzoj3743 Coci2015] Kamp(树形dp)的更多相关文章
- 【BZOJ3743】[Coci2015]Kamp 树形DP
[BZOJ3743][Coci2015]Kamp Description 一颗树n个点,n-1条边,经过每条边都要花费一定的时间,任意两个点都是联通的. 有K个人(分布在K个不同的点)要集中到一个点举 ...
- 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】
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 ...
随机推荐
- 洛谷——P1616 疯狂的采药
https://www.luogu.org/problem/show?pid=1616#sub 题目背景 此题为NOIP2005普及组第三题的疯狂版. 题目描述 LiYuxiang是个天资聪颖的孩子, ...
- Java中的事务
Java中的事务 学习了:https://www.cnblogs.com/chengpeng15/p/5802930.html 膜拜一下 org 分为三类:jdbc事务.jta事务.容器事务:
- redis(四))——多实例化——实现主从配置
引言 redis是一个key-value存储系统. 和Memcached类似,它支持存储的value类型相对很多其它,包含string(字符串).list(链表).set(集合)和zset(有序集合) ...
- APP漏洞自动化扫描专业评测报告(上篇)
一.前言 随着Android操作系统的快速发展,运行于Android之上的APP如雨后春笋般涌现.由于一些APP的开发者只注重APP业务功能的实现,对APP可能出现安全问题不够重视,使得APP存在较多 ...
- SVNserver搭建和使用(二)
上一篇介绍了VisualSVN Server和TortoiseSVN的下载,安装,汉化.这篇介绍一下怎样使用VisualSVN Server建立版本号库,以及TortoiseSVN的使用. 首先打开V ...
- 利用 Gearman 实现系统错误报警功能
Gearman 是什么? Gearman是一个用来把工作委派给其他机器.分布式的调用更适合做某项工作的机器.并发的做某项工作在多个调用间做负载均衡.或用来在调用其它语言的函数的系统. Gearman ...
- Patterns in the Composite Application Library
Patterns in the Composite Application Library Inversion of Control https://www.codeproject.com/Artic ...
- 关于sql2008的数据库导入问题的收集
在下载一个源程序的时候,常常会一起下下来一个数据库,即一个.MDF文件和一个.LDF文件,那么我们如何添加到我们的SQL Server 2008中呢?下面是一些详细的步骤: 1.将.MDF和.LDF文 ...
- 计算机网络自顶向下方法第2章-应用层(application-layer).2
2.4 DNS:因特网的目录服务 2.4.1 DNS提供的服务 DNS的定义 实体层面看,DNS是一个由分层的DNS服务器实现的分布式数据库 协议层面看,DNS是一个使得主机能够查询分布式数据库的应用 ...
- pip换源简易方法
安装pqi >>> pip install pqi 列出pip源 >>> pqi ls 使用pip源 >>> pqi use <name&g ...