NOI03 逃学的小孩

问题描述

Chris家的电话铃响起了,里面传出了Chris的老师焦急的声音:喂,是Chris的家长吗?你们的孩子又没来上课,不想参加考试了吗?一听说要考试,Chris的父母就心急如焚,他们决定在尽量短的时间内找到Chris。他们告诉Chris的老师:根据以往的经验,Chris现在必然躲在朋友ShermieYashiro家里偷玩《拳皇》游戏。现在,我们就从家出发去找Chris,一但找到,我们立刻给您打电话。说完砰的一声把电话挂了。

Chris居住的城市由N个居住点和若干条连接居住点的双向街道组成,经过街道x需花费Tx分钟。可以保证,任两个居住点间有且仅有一条通路。Chris家在点CShermieYashiro分别住在点A和点BChris的老师和Chris的父母都有城市地图,但Chris的父母知道点ABC的具体位置而Chris的老师不知

为了尽快找到ChrisChris的父母会遵守以下两条规则:

l 如果A距离CB距离C近,那么Chris的父母先去Shermie家寻找Chris,如果找不到,Chris的父母再去Yashiro家;反之亦然

l Chris的父母总沿着两点间唯一的通路行走。

这题应该说是树形dp中难度较大的题了。具体参考陈瑜希的论文。

主要思想是通过两遍dfs。第一遍任意选取一个节点作为根,然后求得每个节点子树中前3远的距离。

第二遍dfs是对每个节点求其到其父亲节点引出来的其他节点的最远距离,重新调整每个节点的前3远的距离。

并且第二遍dfs有两个步骤,前一个步骤保证搜索的方向是层次的,这样就能够保证子树更新距离时,父亲节点已更新完毕。

然后为什么父亲节点会引出一条路径。其实是因为每个分叉结点的前3远节点在不同的三颗子树(以该节点为根),也就是三颗子树交于该点,而过该点从其父亲方向过来的只可能有一条,如果大于1条,则说明三颗子树交于多个点组成的线段。

然后可能有人会有疑问?如果仅有一条树链,那么三点不是不交于1点,但是因为我们枚举了所有分叉点,对于这条链上的中间那个点作为分叉点,并且按照论文中转换,也就是添加边权为0的节点,那么就符合题意了,这个在代码里赋初值时是有体现的。但可能有人又有疑问了,其他点作为分叉点,最优解不就不交于1点了。

没错,但是此时根据代码,这些点只会求得以三颗子树交于该点的最优解,因此这些点得不到最优解。但是因为枚举了所有点作为分叉点,所以必然会在以那个中间点作为分叉点时,得到最优解。

所以这些完全不需要担心。。。但是如果你有这些顾虑,那说明你思考问题相当严密,值得鼓励。


代码:

#include
#include
#include
#include
#include
#define ll long long
#define Maxn 200010
using namespace std;

struct edge{
    int u,v;
    ll val;
}p[Maxn];
struct maxx{
    int ori;
    ll dis;
    bool operator<(const maxx &a)const{
        return dis>a.dis;
    }
}ma[Maxn][4];
vector dv[Maxn];
ll ans;
int vis[Maxn];
void dfs1(int u){
    vis[u]=1;
    for(int i=0;i


你可能感兴趣的:(树形dp)