bzoj 3743 [ Coci 2015 ] Kamp —— 树形DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3743
一开始想到了树形DP,处理一下子树中的最小值,向上的最小值,以及子树中的最长路和向上的最长路,就可以得到答案,可以DP;
然而写着写着写不下去了,不会求向上最小值和最长路;
于是看看TJ,原来要再记录一个次长路!
然而写挫了,写不下去了...
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const maxn=5e5+;
int n,m,hd[maxn],ct,fa[maxn],ans[maxn];
ll f[maxn][],g[maxn][],t[maxn],l[maxn][];
bool vis[maxn];
struct N{
int to,nxt,w;
N(int t=,int n=,int w=):to(t),nxt(n),w(w) {}
}ed[maxn<<];
void add(int x,int y,int z){ed[++ct]=N(y,hd[x],z); hd[x]=ct;}
void dfs(int x,int ft)
{
fa[x]=ft;
for(int i=hd[x],u;i;i=ed[i].nxt)
{
if((u=ed[i].to)==ft)continue;
dfs(u,x);
vis[x]|=vis[u];
}
}
void dp(int x)
{
for(int i=hd[x],u;i;i=ed[i].nxt)
{
if((u=ed[i].to)==fa[x])continue;
dp(u);
f[x][]+=(f[u][]+*vis[u]*ed[i].w);
if(l[x][]<l[u][]+vis[u]*ed[i].w)
{
l[x][]=l[x][]; t[x]=u;
l[x][]=l[u][]+vis[u]*ed[i].w;
}
else if(l[x][]<l[u][]+vis[u]*ed[i].w)l[x][]=l[u][]+vis[u]*ed[i].w;
}
f[x][]=f[x][]-l[x][];
}
void dp2(int x)
{
for(int i=hd[x],u;i;i=ed[i].nxt)
{
if((u=ed[i].to)==fa[x])continue;
ans[x]=min(f[x][]+g[x][],f[x][]+g[x][]);
g[u][]=g[x][]+f[x][]-f[u][];
if(u==t[x])g[u][]=min(g[x][]+f[x][]-f[u][],g[u][]-l[x][])-ed[i].w;
else g[u][]=min(g[x][]+f[x][]-f[u][],g[u][]-l[x][]);
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=,x,y,z;i<n;i++)
{
scanf("%d%d%d",&x,&y,&z);
add(x,y,z); add(y,x,z);
}
for(int i=,x;i<=m;i++)
scanf("%d",&x),vis[x]=;
dfs(,); dp(); dp2();
for(int i=;i<=n;i++)printf("%lld\n",ans[i]);
return ;
}
囧
然后滚去看TJ,再次学习了一下优美的树形DP写法...
dis[x] 表示总路长,f[x][0] 表示子树中最长路,f[x][1] 表示子树中次长路,f[x][2] 表示向上最长路;
然后优美 dfs 即可...
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const maxn=5e5+,inf=0x3f3f3f3f;
int n,m,hd[maxn],ct,siz[maxn];
ll dis[maxn],f[maxn][];
bool vis[maxn];
struct N{
int to,nxt,w;
N(int t=,int n=,int w=):to(t),nxt(n),w(w) {}
}ed[maxn<<];
void add(int x,int y,int z){ed[++ct]=N(y,hd[x],z); hd[x]=ct;}
void dfs(int x,int fa)
{
// dis[x]=(vis[x]?0:-inf);
// siz[x]=(vis[x]?1:0);
siz[x]=vis[x]; dis[x]=;
for(int i=hd[x],u;i;i=ed[i].nxt)
{
if((u=ed[i].to)==fa)continue;
dfs(u,x); siz[x]+=siz[u];
// dis[x]+=dis[u]+ed[i].w;
dis[x]+=dis[u]+(siz[u]?ed[i].w:);
}
}
void dfs2(int x,int fa)
{
for(int i=hd[x],u;i;i=ed[i].nxt)
{
if((u=ed[i].to)==fa)continue;
dis[u]=dis[x];//
if(siz[u])dis[u]-=ed[i].w;
if(siz[u]<m)dis[u]+=ed[i].w;//siz[u]==0
dfs2(u,x);
}
}
void dfs3(int x,int fa)
{
f[x][]=f[x][]=(vis[x]?:(ll)-inf*inf);
for(int i=hd[x],u;i;i=ed[i].nxt)
{
if((u=ed[i].to)==fa)continue;
dfs3(u,x);
if(f[u][]+ed[i].w>f[x][])
{
f[x][]=f[x][];
f[x][]=f[u][]+ed[i].w;
}
else if(f[u][]+ed[i].w>f[x][])f[x][]=f[u][]+ed[i].w;
}
}
void dfs4(int x,int fa)
{
for(int i=hd[x],u;i;i=ed[i].nxt)
{
if((u=ed[i].to)==fa)continue;
if(f[u][]+ed[i].w==f[x][])f[u][]=f[x][]+ed[i].w;
else f[u][]=f[x][]+ed[i].w;
f[u][]=max(f[u][],f[x][]+ed[i].w);
dfs4(u,x);
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=,x,y,z;i<n;i++)
{
scanf("%d%d%d",&x,&y,&z);
add(x,y,z); add(y,x,z);
}
for(int i=,x;i<=m;i++)scanf("%d",&x),vis[x]=;
dfs(,); dfs2(,); dfs3(,);
f[][]=(vis[]?:(ll)-inf*inf); dfs4(,);
for(int i=;i<=n;i++)printf("%lld\n",*dis[i]-max(f[i][],f[i][]));
return ;
}
bzoj 3743 [ Coci 2015 ] Kamp —— 树形DP的更多相关文章
- [BZOJ 4033] [HAOI2015] T1 【树形DP】
题目链接:BZOJ - 4033 题目分析 使用树形DP,用 f[i][j] 表示在以 i 为根的子树,有 j 个黑点的最大权值. 这个权值指的是,这个子树内部的点对间距离的贡献,以及 i 和 Fat ...
- [BZOJ 3992] [SDOI 2015] 序列统计(DP+原根+NTT)
[BZOJ 3992] [SDOI 2015] 序列统计(DP+原根+NTT) 题面 小C有一个集合S,里面的元素都是小于质数M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数 ...
- [BZOJ 4455] [ZJOI 2016] 小星星 (树形dp+容斥原理+状态压缩)
[BZOJ 4455] [ZJOI 2016] 小星星 (树形dp+容斥原理+状态压缩) 题面 给出一棵树和一个图,点数均为n,问有多少种方法把树的节点标号,使得对于树上的任意两个节点u,v,若树上u ...
- bzoj 3743 [Coci2015]Kamp——树形dp+换根
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3743 树形dp+换根. “从根出发又回到根” 减去 “mx ” . 注意dfsx里真的要改那 ...
- 【BZOJ3743】[Coci2015]Kamp 树形DP
[BZOJ3743][Coci2015]Kamp Description 一颗树n个点,n-1条边,经过每条边都要花费一定的时间,任意两个点都是联通的. 有K个人(分布在K个不同的点)要集中到一个点举 ...
- 『kamp 树形dp』
kamp Description jz 市的云台山是个很美丽的景区,小 x 暑期到云台山打工,他的任务是开景区的大巴. 云台山景区有 N 个景点,这 N 个景点由 N-1 条道路连接而成,我们保证这 ...
- BZOJ 2286 消耗战 (虚树+树形DP)
给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...
- BZOJ 2435 道路修建 NOI2011 树形DP
一看到这道题觉得很水,打了递归树形DP后RE了一组,后来发现必须非递归(BFS) 递归版本84分: #include<cstdio> #include<cstring> #in ...
- BZOJ 2878: [Noi2012]迷失游乐园( 树形dp )
一棵树的话直接树形dp(求出往下走和往上走的期望长度). 假如是环套树, 环上的每棵树自己做一遍树形dp, 然后暴力枚举(环上的点<=20)环上每个点跑经过环上的路径就OK了. -------- ...
随机推荐
- CentOS 7 使用 yum 安装 MariaDB 与 MariaDB 的简单配置
闲置已久的空间环境配置忘得差不多了,今天得空整理,重置了磁盘重新搭建环境,首先安装MariaDB的数据库,在这里记录下安装过程,以便以后查看. 1.安装MariaDB 安装命令 yum -y inst ...
- (转)Hibernate的优化方案
http://blog.csdn.net/yerenyuan_pku/article/details/70768603 HQL优化 使用参数绑定 使用绑定参数的原因是让数据库一次解析SQL,对后续的 ...
- 前端精选文摘:css之GFC 神奇背后的原理(整理)
CSS3 Grid Layout Web页面的布局,我们常见的主要有“浮动布局(float)”.“定位布局(position)”.“行内块布局(inline-block)”.“CSS3的多栏布局(Co ...
- 【LeetCode】4、Median of Two Sorted Arrays
题目等级:Hard 题目描述: There are two sorted arrays nums1 and nums2 of size m and n respectively. Find t ...
- 计蒜客 成绩统计 (Hash表)
链接 : Here! 思路 : 如果用 $STL$ 的 $map$ 或者是使用 $unordered\underline{}map$ 的话是会 $T$ 的, 所以得手写一个 $hash表$. 其实这个 ...
- 小实例 hangman game
代码 #include <bits/stdc++.h> using namespace std; int bk[110]; string sj(int t) { string ans=&q ...
- 面试题:你能写一个Vue的双向数据绑定吗?
在目前的前端面试中,vue的双向数据绑定已经成为了一个非常容易考到的点,即使不能当场写出来,至少也要能说出原理.本篇文章中我将会仿照vue写一个双向数据绑定的实例,名字就叫myVue吧.结合注释,希望 ...
- python爬虫12 | 爸爸,他使坏,用动态的 Json 数据,我要怎么搞?
在前面我们玩了好多静态的 HTML 想必你应该知道怎么去爬这些数据了 但还有一些常见的动态数据 比如 商品的评论数据 实时的直播弹幕 岛国动作片的评分 等等 这些数据是会经常发生改变的 很多网站就会用 ...
- 2019-02-13 Python爬虫问题 NotImplementedError: Only the following pseudo-classes are implemented: nth-of-type.
soup=BeautifulSoup(html.text,'lxml') #data=soup.select('body > div.main > div.ctr > div > ...
- Linux下几种文件传输命令
Linux下几种文件传输命令 sz rz sftp scp 最近在部署系统时接触了一些文件传输命令,分别做一下简单记录: 1.sftp Secure Ftp 是一个基于SSH安全协议的文件传输管理工具 ...