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了. -------- ...
随机推荐
- 白盒-CNN纹理深度可视化: 使用MIT Place 场景预训练模型
MIT发文:深度视觉的量化表示................ Places2 是一个场景图像数据集,包含 1千万张 图片,400多个不同类型的场景环境,可用于以场景和环境为应用内容的视觉认知任务. ...
- CAD动态绘制样条线(com接口)
主要用到函数说明: _DMxDrawX::SendStringToExecuteFun 把命令当着函数执行,可以传参数.详细说明如下: 参数 说明 IDispatch* pParam 命令参数,IMx ...
- 10java内存
java内存 1.栈---存储的是变量(不仅仅只有变量),不会对存储的内容进行赋值,存储的内容使用完成之后会立即进行清除 2.堆---存储的是对象.会对存储的内容进行赋值,存储内容使用完成之后会在某个 ...
- Problem 21
Problem 21 https://projecteuler.net/problem=21 Let d(n) be defined as the sum of proper divisors of ...
- GitHub:创建和修改远程仓库
创建远程仓库 首先在GitHub上创建一个仓库命名为learngit.选中public(private要钱),选中 生成README(就是markdown形式的说明文档),便于别人和自己了解仓库的作用 ...
- [国家集训队2012]tree(陈立杰)
[国家集训队2012]tree(陈立杰) 题目 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有need条白色边的生成树.题目保证有解. INPUT 第一行V,E,need分别表示 ...
- python实现字符串之间的映射
类似于凯撒密码一样的加密 # *-* coding=utf-8 *-* import string intab = string.lowercase outtab = 'qwertyuiopasdfg ...
- 【ACM】hdu_1004_Let the Balloon Rise_201308141026-2
Let the Balloon RiseTime Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Othe ...
- [bzoj4010][HNOI2015]菜肴制作_贪心_拓扑排序
菜肴制作 bzoj-4010 HNOI-2015 题目大意:给定一张n个点m条边的有向图,求一个toposort,使得:(1)满足编号为1的点尽量在前:(2)满足(1)的情况下编号为2的点尽量在前,以 ...
- SSM(spring mvc+spring+mybatis)学习路径——2-1、spring MVC入门
目录 2-1 Spring MVC起步 一.回顾Servlet 二.SpringMVC简介 三.搭建SpringMVC第一个案例 四.简单流程及配置 五.使用注解开发Controller 六.参数绑定 ...