题目: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的更多相关文章

  1. [BZOJ 4033] [HAOI2015] T1 【树形DP】

    题目链接:BZOJ - 4033 题目分析 使用树形DP,用 f[i][j] 表示在以 i 为根的子树,有 j 个黑点的最大权值. 这个权值指的是,这个子树内部的点对间距离的贡献,以及 i 和 Fat ...

  2. [BZOJ 3992] [SDOI 2015] 序列统计(DP+原根+NTT)

    [BZOJ 3992] [SDOI 2015] 序列统计(DP+原根+NTT) 题面 小C有一个集合S,里面的元素都是小于质数M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数 ...

  3. [BZOJ 4455] [ZJOI 2016] 小星星 (树形dp+容斥原理+状态压缩)

    [BZOJ 4455] [ZJOI 2016] 小星星 (树形dp+容斥原理+状态压缩) 题面 给出一棵树和一个图,点数均为n,问有多少种方法把树的节点标号,使得对于树上的任意两个节点u,v,若树上u ...

  4. bzoj 3743 [Coci2015]Kamp——树形dp+换根

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3743 树形dp+换根. “从根出发又回到根” 减去 “mx ” . 注意dfsx里真的要改那 ...

  5. 【BZOJ3743】[Coci2015]Kamp 树形DP

    [BZOJ3743][Coci2015]Kamp Description 一颗树n个点,n-1条边,经过每条边都要花费一定的时间,任意两个点都是联通的. 有K个人(分布在K个不同的点)要集中到一个点举 ...

  6. 『kamp 树形dp』

    kamp Description jz 市的云台山是个很美丽的景区,小 x 暑期到云台山打工,他的任务是开景区的大巴. 云台山景区有 N 个景点,这 N 个景点由 N-1 条道路连接而成,我们保证这 ...

  7. BZOJ 2286 消耗战 (虚树+树形DP)

    给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...

  8. BZOJ 2435 道路修建 NOI2011 树形DP

    一看到这道题觉得很水,打了递归树形DP后RE了一组,后来发现必须非递归(BFS) 递归版本84分: #include<cstdio> #include<cstring> #in ...

  9. BZOJ 2878: [Noi2012]迷失游乐园( 树形dp )

    一棵树的话直接树形dp(求出往下走和往上走的期望长度). 假如是环套树, 环上的每棵树自己做一遍树形dp, 然后暴力枚举(环上的点<=20)环上每个点跑经过环上的路径就OK了. -------- ...

随机推荐

  1. JS——void(0)

    a标签中阻止跳转: <a href="javascript:;">跳转</a> <a href="javascript:void(0)&qu ...

  2. 【sqli-labs】 less58 GET -Challenge -Double Query -5 queries allowed -Variation1 (GET型 挑战 双查询 只允许5次查询 变化1)

    单引号闭合成功,但是union select结果不对 http://192.168.136.128/sqli-labs-master/Less-58/?id=0' union select 1,2,3 ...

  3. 如何从源码启动和编译IoTSharp

    IoTSharp 项目是一个开源物联网平台,数据库使用PostgreSQL , 后端使用 Asp.Net Core 2.2 ,前端使用  vue-element-admin , 下面我们介绍如何启动项 ...

  4. CAD保存DWG文件,设置保存的文件版本号和密码

    主要用到函数说明: MxDrawXCustomFunction::Mx_SaveDwgEx 保存DWG文件,可以设置保存的文件版本号和密码,详细说明如下: 参数 说明 IN CString sFile ...

  5. Python-暑期实训day 1

    python基础: 一 编程语言 什么是编程语言? 上面提及的能够被计算机所识别的表达方式即编程语言,语言是沟通的介质,而编程语言是程序员与计算机沟通的介质.在编程的世界里,计算机更像是人的奴隶,人类 ...

  6. 初级模拟电路:3-1 BJT概述

    回到目录 1.   名称由来 BJT的全称是双极性结型晶体管(Bipolar Junction Transistor),国内俗称三极管.其实,在英语中,三极管(triode)特指以前的真空电子管形式的 ...

  7. SSHFS使用笔记

    在写树莓派集群项目的时候,发现如果在树莓派上维护的代码需要非常费力才能跟本地项目代码同步,因此打算将Server端和Client端代码分开,树莓派上的Client端代码远程挂载到本地,这样做比之前要更 ...

  8. PHP常用系统设置整理

    1.设置时间脚本执行时间 set_time_limit(0); 2.设置最大执行内存 ini_set('memory_limit','1024M');//设置内存 memory_get_usage() ...

  9. 对vuex的浅解

    vuex是什么? 官网的解释是 Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化.Vuex 也 ...

  10. hdu 3572 最大流判断满流

    #include<stdio.h> #include<string.h> #include<queue> using namespace std; #define ...