P6419 COCI2014-2015#1 Kamp

换根 \(dp\) 的 trick。

题面

钦定 \(k\) 个关键点,求每个点出发,访问完所有关键点的距离最小值。

思路

设 \(g_u\) 为从点 \(u\) 出发,访问完子树内所有关键点后,回到点 \(u\) 的距离最小值。

\(s_u\) 为点 \(u\) 子树内关键点个数,\(E(u,v)\) 为边权。

\[g_u=\sum_{v\in u.sons} g_v+ E(u,v)\times 2 \times [s_u>0]
\]

自然我们需要换根 dp 求出每个点作为根的时候的 \(g_u\),设这个答案为 \(f_u\)​​。

\(f\) 为 \(u\) 的父亲。

考虑换根转移:

  1. 若 \(s_u=0\),则 \(f_u=g_f+E(f,u)\times 2\),画图显而易见。
  2. 若 \(k-s_u=0\),则 \(f_u=g_u\),都在 \(u\) 的子树内,也显而易见。
  3. 其他情况,则 \(f_u=f_f\),把 \(u\) 作为根,仔细观察一下我们更新的递推式,你会发现 \(f_u=f_f-(g_u-E(u,f))+(g_u+E(u,f))\),化简即可得。

由于车开到最后一个关键点可以不返回 \(u\) 点,而最小访问距离是可以有多重解法的,肯定存在一种方案使得最后访问最距离 \(u\) 最远的点,这样就可以剩下最大距离不用返回 \(u\)​​ 点。

下文所述的最长链,次长连均为关键点作为链的一端的链。

这个貌似可以使用 dfn 序+线段树维护最长链,单次查询复杂度 \(O(\log n)\),但这里也可以利用换根 dp 求最长链。

下面是利用换根 dp 求最长链的思路。

设 \(u\) 子树内到 \(u\) 的最长链长度为 \(len_u\),来自 \(u\) 的儿子 \(id_u\)。

设 \(u\) 子树内到 \(u\) 的次长链长度为 \(slen_u\),要求与 \(len_u\) 来自的儿子不相同。

\(v\) 为 \(u\) 的儿子,有转移:

  1. 若 \(len_u<len_v+E(u,v)\),则 \(slen_u\gets len_u,len_u\gets len_v+E(u,v),id_u\gets v\)。
  2. 若不满足 1 且 \(slen_u<len_v+E(u,v)\),则 \(slen_u\gets len_v+E(u,v)\)​。

变换 \(len_u\) 的意义为到 \(u\) 点的最长链,\(slen_u\) 的意义为和 \(len_u\) 来自不同的 \(u\)​ 所相接的边的次长链。

易得根的 \(len\) 与 \(slen\) 为原来的值。

设 \(f\) 为 \(u\) 的父亲,考虑从根开始的换根转移:

  1. 若 \(len_u<len_f+E(u,f)\) 且 \(id_f\neq u\),则 \(slen_u\gets len_u,len_u\gets len_f+E(u,f),id_u\gets f\)。
  2. 若 \(len_u<slen_f+E(u,f)\),则 \(len_u\gets slen_f+E(u,f),id_u\gets -1\),此时​无论 \(id_u\) 取何值,都不影响下一步转移。
  3. 若 \(slen_u<len_f+E(u,f)\) 且 \(id_f\neq u\),则 \(slen_u\gets len_f+E(u,f)\)​。
  4. 若 \(slen_u<slen_f+E(u,f)\),则 \(slen_u\gets slen_f+E(u,f)\)。

满足上述转移中最靠前的一条,便可以退出转移。

到这里我们变可以输出答案 \(f_i-len_i\)。

CODE

#include<bits/stdc++.h>
using namespace std; #define ll long long const int maxn=5e5+5; struct Edge
{
int tot;
int head[maxn];
struct edgenode{int to,nxt,val;}edge[maxn*2];
inline void add(int x,int y,int z)
{
tot++;
edge[tot].to=y;
edge[tot].nxt=head[x];
edge[tot].val=z;
head[x]=tot;
}
}T; int n,k;
int s[maxn],id[maxn]; ll dp[maxn],f[maxn],len[maxn],slen[maxn]; inline int Max(int a,int b)
{
if(a<b) return b;
else return a;
}
inline void dfs_fir(int u,int fa)
{
for(int i=T.head[u];i;i=T.edge[i].nxt)
{
int v=T.edge[i].to;
if(v==fa) continue;
dfs_fir(v,u);s[u]+=s[v];
}
for(int i=T.head[u];i;i=T.edge[i].nxt)
{
int v=T.edge[i].to,w=T.edge[i].val;
if(v==fa) continue;
if(!s[v]) continue;
dp[u]+=dp[v]+w*2;
if(len[v]+w>=len[u]) slen[u]=len[u],len[u]=len[v]+w,id[u]=v;
else if(len[v]+w>=slen[u]) slen[u]=len[v]+w;
}
}
inline void dfs_sec(int u,int fa)
{
for(int i=T.head[u];i;i=T.edge[i].nxt)
{
int v=T.edge[i].to,w=T.edge[i].val;
if(v==fa) continue;
if(!s[v]) f[v]=f[u]+w*2,len[v]=len[u]+w;
else if(k-s[v])
{
f[v]=f[u];
if(id[u]!=v&&len[v]<len[u]+w) slen[v]=len[v],len[v]=len[u]+w,id[v]=u;
else if(len[v]<slen[u]+w) slen[v]=len[v],len[v]=slen[u]+w,id[v]=-1;
else if(id[u]!=v&&slen[v]<len[u]+w) slen[v]=len[u]+w;
else if(slen[v]<slen[u]+w) slen[v]=slen[u]+w;
}
else f[v]=dp[v];
dfs_sec(v,u);
}
} int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<n;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
T.add(x,y,z),T.add(y,x,z);
}
for(int i=1;i<=k;i++)
{
int x;
scanf("%d",&x);
s[x]=1;
}
dfs_fir(1,0);
f[1]=dp[1];
dfs_sec(1,1);
for(int i=1;i<=n;i++) printf("%lld\n",f[i]-len[i]);
}

后记

这个 trick 相较于数据结构优势在于可以 \(O(1)\),劣势在于不可以在线。

P6419 COCI2014-2015#1 Kamp的更多相关文章

  1. COCI2014/2015 Contest#1 D MAFIJA【基环树最大独立点集】

    T1725 天黑请闭眼 Online Judge:COCI2014/2015 Contest#1 D MAFIJA(原题) Label:基环树,断环+树形Dp,贪心+拓扑 题目描述 最近天黑请闭眼在 ...

  2. 2018-2-6考试(COCI2014/2015 Contest#5)

    T1:FUNGHI(1s,32M,50pts)得分:50 题意:给你8个数组成一个环,要你求出其中连续的4个数,让它们的和最大 题解:暴力求出每一连续4个数之和,比较一下就好 标签:模拟 C++ Co ...

  3. C++算法代码——求数列[coci2014/2015 contest #1]

    题目来自:http://218.5.5.242:9018/JudgeOnline/problem.php?id=1815 题目描述 Mirko在数学课上以一种有趣的方式操作数列,首先,他写下一个数列A ...

  4. [Bzoj3743][Coci2015] Kamp【换根Dp】

    Online Judge:Bzoj3743 Label:换根Dp,维护最长/次长链 题目描述 一颗树n个点,n-1条边,经过每条边都要花费一定的时间,任意两个点都是联通的. 有K个人(分布在K个不同的 ...

  5. BZOJ3743 : [Coci2014]Kamp

    d[x][0]表示x点向下走且回到x点的最少代价 d[x][1]表示x点向下走但不回到x点的最少代价 d[x][2]表示x点向下走的最长路 d[x][3]表示x点向下走的次长路 u[x][0]表示x点 ...

  6. bzoj 3743 [ Coci 2015 ] Kamp —— 树形DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3743 一开始想到了树形DP,处理一下子树中的最小值,向上的最小值,以及子树中的最长路和向上的 ...

  7. 洛谷 P6419 Kamp 题解

    明天就SX AFO了交篇题解%一下 这题大概是我第一道有独立思考切掉的紫题 之前的都是各种抄借鉴题解 为什么写这题的题解呢?另一个重要的原因是这样的↓ 翻了翻已有题解中的几篇,下面几种情况屡见不鲜 样 ...

  8. 2015 西雅图微软总部MVP峰会记录

    2015 西雅图微软总部MVP峰会记录 今年决定参加微软MVP全球峰会,在出发之前本人就已经写这篇博客,希望将本次会议原汁原味奉献给大家 因为这次是本人第一次写会议记录,写得不好的地方希望各位园友见谅 ...

  9. 使用Visual Studio 2015 开发ASP.NET MVC 5 项目部署到Mono/Jexus

    最新的Mono 4.4已经支持运行asp.net mvc5项目,有的同学听了这句话就兴高采烈的拿起Visual Studio 2015创建了一个mvc 5的项目,然后部署到Mono上,浏览下发现一堆错 ...

  10. TFS 2015 敏捷开发实践 – 在Kanban上运行一个Sprint

    前言:在 上一篇 TFS2015敏捷开发实践 中,我们给大家介绍了TFS2015中看板的基本使用和功能,这一篇中我们来看一个具体的场景,如何使用看板来运行一个sprint.Sprint是Scrum对迭 ...

随机推荐

  1. zabbix报错大全

    zabbix报错 https://www.cnblogs.com/losbyday/category/876878.html作者总结的很全棒 1.在启动zabbix-agent 时系统日志输出 PID ...

  2. 构建 OpenWrt

    OpenWrt 是一款路由器操作系统.如果你想要给自己的路由器安装 OpenWrt 的话,一般来说使用别人已经构建好的 OpenWrt 固件就够用了.当然如果你闲得没事干,那么也可以自己构建固件. P ...

  3. openFile(/tmp/spring.log,true) call failed. java.io.FileNotFoundException: /tmp/spring.log (Permission denied)

    ERROR [main] SpringApplication: Application run failed java.lang.IllegalStateException: Logback conf ...

  4. Python将表格文件中某些列的数据整体向上移动一行

      本文介绍基于Python语言,针对一个文件夹下大量的Excel表格文件,对其中的每一个文件加以操作--将其中指定的若干列的数据部分都向上移动一行,并将所有操作完毕的Excel表格文件中的数据加以合 ...

  5. AGC007F 题解

    题意 给定两个长为 \(n\) 的字符串 \(S, T\),求最少进行多少次操作才能使 \(S = T\). 一次操作定义为:对于 \(i = 1, 2, .. n\),令第 \(i\) 位为操作后的 ...

  6. 使用gin实现简单的注册和登录功能

    一.前言 使用了gorm操作数据库,后端基于gin框架,只是一个简单的注册和登录与数据库交互的后端实现例子. 二.目录结构 -templates --regist.html --login.html ...

  7. 聊聊 iframe, CSP, 安全, 跨域

    refer : https://www.cnblogs.com/kunmomo/p/12131818.html (跨域) https://segmentfault.com/a/119000000450 ...

  8. Tomcat——基本使用(下载、安装、卸载、启动、关闭)

    Tomcat--基本使用   1.下载安装(8.5版本为企业最常用版本)     下载地址:https://tomcat.apache.org/download-80.cgi          (官网 ...

  9. 安装windows11系统跳过微软账号登录,使用本地账号登录方法

    在安装win11系统,进行到如图下所示界面的时候,暂停下 我们可以按下键盘的Shift+F10按键(部分电脑是Fn+Shift+F10),这时屏幕会出现命令行窗口,如图下所示 我们需要在命令行内输入代 ...

  10. 《MySQL 5.7从入门到精通(视频教学版)》代码课件教学视频下载

    <MySQL 5.7从入门到精通(视频教学版)>代码课件教学视频下载 https://pan.baidu.com/s/1ZufDV6a_PEnjp-Bdh4IkuQ 提取码:vgnr 无版 ...