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了. -------- ...
随机推荐
- JS高级——变量提升
JS执行过程 1.首先是预解析:预解析过程最重要的是提升,在JavaScript代码在预解析阶段,会对以var声明的变量名,和function开头的语句块,进行提升操作 2.执行操作 全局中解析和执行 ...
- html5——盒子模式
box-sizing属性 box-sizing: border-box;/*内减模式*/ box-sizing: content-box;/*外加模式(默认值)*/ box-sizing: paddi ...
- CentOS7将firewall切换为iptables防火墙
- (转) Hibernate检索方式概述
http://blog.csdn.net/yerenyuan_pku/article/details/70554816 Hibernate检索方式概述 我们在对数据库的操作中,最常用的是select, ...
- JS实现随机颜色的3种方法与颜色格式的转化
JS实现随机颜色的3种方法与颜色格式的转化 随机颜色和颜色格式是我们在开发中经常要用到的一个小功能,网上相关的资料也很多,想着有必要总结一下自己的经验.所以这篇文章主要介绍了JS实现随机颜色的3种 ...
- How To:python pip install
官方网站 https://pypi.python.org/pypi/pip/ 下载需要的版本 wget https://pypi.python.org/packages/source/p/pi ...
- uva340 Master-Mind Hints (UVA - 340)
题目简要 题目意思很简单每个测试都由原题目在第一行,然后后面的都是去猜的答案,如果猜测的位置正确那么输出的结果的数对里面的第一个数就加一,如果仅答案正确(原题目里有这个数,但是位置不一样)那么就在输出 ...
- 48.cartinality的基本用法
主要知识点 cartinality的用法 es去重用的是cartinality metric算法,对每个bucket中的指定的field进行去重,然后获取去重后的count,类似于count( ...
- PAT 1104 Sum of Number Segments
Given a sequence of positive numbers, a segment is defined to be a consecutive subsequence. For exam ...
- jquery源码分析(四)——回调对象 Callbacks
借用百度百科来说明下回调函数: 回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数.回调函数不是由该 ...