问题描述

W 国的交通呈一棵树的形状。W 国一共有n - 1个城市和n个乡村,其中城市从1到n - 1 编号,乡村从1到n编号,且1号城市是首都。道路都是单向的,本题中我们只考虑从乡村通往首都的道路网络。对于每一个城市,恰有一条公路和一条铁路通向这座城市。对于城市i, 通向该城市的道路(公路或铁路)的起点,要么是一个乡村,要么是一个编号比ii大的城市。 没有道路通向任何乡村。除了首都以外,从任何城市或乡村出发只有一条道路;首都没有往 外的道路。从任何乡村出发,沿着唯一往外的道路走,总可以到达首都。

W 国的国王小 W 获得了一笔资金,他决定用这笔资金来改善交通。由于资金有限,小 W 只能翻修n - 1条道路。小 W 决定对每个城市翻修恰好一条通向它的道路,即从公路和铁 路中选择一条并进行翻修。小 W 希望从乡村通向城市可以尽可能地便利,于是根据人口调 查的数据,小 W 对每个乡村制定了三个参数,编号为ii的乡村的三个参数是ai,bi和ci。假设 从编号为i的乡村走到首都一共需要经过x条未翻修的公路与y条未翻修的铁路,那么该乡村 的不便利值为

\[c_i \cdot (a_i + x) \cdot (b_i + y)
\]

在给定的翻修方案下,每个乡村的不便利值相加的和为该翻修方案的不便利值。 翻修n - 1条道路有很多方案,其中不便利值最小的方案称为最优翻修方案,小 W 自然 希望找到最优翻修方案,请你帮助他求出这个最优翻修方案的不便利值。

输入格式

第一行为正整数n。

接下来n - 1行,每行描述一个城市。其中第i行包含两个数si,ti。si表示通向第i座城市 的公路的起点,ti表示通向第i座城市的铁路的起点。如果si > 0,那么存在一条从第si座城 市通往第i座城市的公路,否则存在一条从第-si个乡村通往第i座城市的公路;ti类似地,如 果ti >,那么存在一条从第ti座城市通往第i座城市的铁路,否则存在一条从第-ti个乡村通 往第i座城市的铁路。

接下来n行,每行描述一个乡村。其中第i行包含三个数ai,bi,ci,其意义如题面所示。

输出格式

输出一行一个整数,表示最优翻修方案的不便利值。

样例输入

6

2 3

4 5

-1 -2

-3 -4

-5 -6

1 2 3

1 3 2

2 1 3

2 3 1

3 1 2

3 2 1

样例输出

54

解析

由题目的意思,最后构成的树有这些特征:叶节点都是乡村;每个城市只有两个儿子,且一个是公路,一个是铁路。考虑阶段为当前到了哪个点。描述一个状态则需要知道经过了多少公路,多少铁路。所以,我们设计状态如下:

设\(f[x][l][r]\)表示当前在x点,经过了l条未翻修的公路、r条未翻修的铁路的最小不方便值。考虑到正着并不好推,我们尝试着倒着推。每个点只会被两个子节点更新,且一个子节点是经过公路,一个是经过铁路。不难得到,我们有如下方程:

\[f[x][l][r]=min(f[ls[x]][l+1][r],f[rs[x]][l][r+1])
\]

当x为叶节点时,由题中的式子,我们可以得到如下初始状态:

\[f[x][l][r]=c_i*(a_i+l)*(b_i+r)
\]

在dfs时,为了优化时间,我们需要记下当前最多会经过多少条没有翻修的公路和铁路。但是,这并不能解决空间的问题。可以发现,每次结束递归的点此后都不会再调用,所以我们可以每次给一个点一个编号,结束递归回收利用编号,就可以做到优化空间了。

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#define int long long
#define N 40002
using namespace std;
int n,i,a[N],b[N],c[N],ls[N],rs[N],f[102][42][42],dfn[N];
int read()
{
char c=getchar();
int w=0,f=1;
while(c<'0'||c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c<='9'&&c>='0'){
w=w*10+c-'0';
c=getchar();
}
return w*f;
}
void dfs(int x,int l,int r,int tim)
{
dfn[x]=tim;
if(x>=n){
for(int i=0;i<=l;i++){
for(int j=0;j<=r;j++) f[dfn[x]][i][j]=c[x]*(a[x]+i)*(b[x]+j);
}
return;
}
dfs(ls[x],l+1,r,tim+1);
dfs(rs[x],l,r+1,tim+2);
int pl=dfn[ls[x]],pr=dfn[rs[x]];
for(int i=0;i<=l;i++){
for(int j=0;j<=r;j++){
f[dfn[x]][i][j]=min(f[pl][i][j]+f[pr][i][j+1],f[pl][i+1][j]+f[pr][i][j]);
}
}
}
signed main()
{
n=read();
for(i=1;i<=n-1;i++){
ls[i]=read(),rs[i]=read();
if(ls[i]<0) ls[i]=-ls[i]+n-1;
if(rs[i]<0) rs[i]=-rs[i]+n-1;
}
for(i=n;i<=2*n-1;i++) a[i]=read(),b[i]=read(),c[i]=read();
memset(f,0x3f,sizeof(f));
dfs(1,0,0,1);
printf("%lld\n",f[1][0][0]);
return 0;
}

反思

  • 没有看到路径长度小于等于40的条件,导致半天没有设计状态的思路。
  • 正难则反,老是想着从上到下,没有想过可以从叶节点出发倒推得到答案。

[洛谷P4438] HNOI2018 道路的更多相关文章

  1. 洛谷4438 [Hnoi2018]道路 【树形dp】

    题目 题目太长懒得打 题解 HNOI2018惊现普及+/提高? 由最长路径很短,设\(f[i][x][y]\)表示\(i\)号点到根有\(x\)条未修公路,\(y\)条未修铁路,子树所有乡村不便利值的 ...

  2. 洛谷 P5019 铺设道路

    题目描述 春春是一名道路工程师,负责铺设一条长度为 \(n\) 的道路. 铺设道路的主要工作是填平下陷的地表.整段道路可以看作是 \(n\) 块首尾相连的区域,一开始,第 \(i\) 块区域下陷的深度 ...

  3. 洛谷P4438 [HNOI/AHOI2018]道路(dp)

    题意 题目链接 Sol 每当出题人想起他出的HNOI 2018 Day2T3,他都会激动的拍打着轮椅 读题比做题用时长系列... \(f[i][a][b]\)表示从根到\(i\)的路径上,有\(a\) ...

  4. 洛谷P4438 道路 [HNOI/AHOI2018] 树形dp

    正解:树形dp 解题报告: 传送门! 昂首先看懂题目趴QwQ大概就是说有棵满二叉树,有n个叶子节点(乡村)和n-1个非叶子节点,然后这棵树的每个节点有三个属性abc,对每个非叶子节点可以从与子节点的两 ...

  5. [NOIP2014] 提高组 洛谷P2296 寻找道路

    题目描述 在有向图G 中,每条边的长度均为1 ,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件: 1 .路径上的所有点的出边所指向的点都直接或间接与终点连通. 2 .在满足条 ...

  6. NOIP2014 day2 T2 洛谷P2296 寻找道路

    题目描述 在有向图G 中,每条边的长度均为1 ,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件: 1 .路径上的所有点的出边所指向的点都直接或间接与终点连通. 2 .在满足条 ...

  7. 洛谷 P1272 重建道路 解题报告

    P1272 重建道路 题目描述 一场可怕的地震后,人们用\(N\)个牲口棚\((1≤N≤150\),编号\(1..N\))重建了农夫\(John\)的牧场.由于人们没有时间建设多余的道路,所以现在从一 ...

  8. 洛谷 P2505 [HAOI2012]道路 解题报告

    P2505 [HAOI2012]道路 题目描述 C国有n座城市,城市之间通过m条单向道路连接.一条路径被称为最短路,当且仅当不存在从它的起点到终点的另外一条路径总长度比它小.两条最短路不同,当且仅当它 ...

  9. 洛谷P3639 [APIO2013] 道路费用 [生成树的特殊算法]

    题目传送门 道路费用 格式难调,题面就不放了. 分析: 这是一道要细(yan)心(jing)的生成树的好(gui)题. 首先我们看到$k$的范围非常小,那么我们就可以直接$2^k$枚举每一条加边是否选 ...

随机推荐

  1. Git 版本管理工具命令速查

    转自:http://www.jb51.net/article/55442.htm 一. Git 常用命令速查 git branch 查看本地所有分支git status 查看当前状态 git comm ...

  2. 阶段3 1.Mybatis_09.Mybatis的多表操作_3 完成account的一对一操作-通过写account的子类方式查询

    先把多表查询的sql语句写出来 想要显示的字段 创建一个AccountUser类 继承Account.这样它就会从父类上继承一些信息 这里只需要定义username和address就可以了 .然后生成 ...

  3. JS中设置cookie,读取cookie,删除cookie

    在开发时,碰到一个需求,需要保存一个表的信息(非隐私),希望下次打开还存在.于是想到用cookie,一番折腾完成.示例数据都是假的,打马赛克是怕泄密. 这个表取名为Data,为Array,每一行是一个 ...

  4. 测开之路一百二十七:flask之构造response对象

    可以使用flask.make_response构造自定义响应信息 构造一个响应信息为文本,状态码为404 响应 响应数据为json,状态码为200 返回html # coding:utf-8from ...

  5. 移动端自动化==>Appium定位方式总结

    1.ID Android Android的resource-id对应ID定位方式,可以通过index来获取需要的元素(从0开始查找dom树中的同名resource-id属性).使用appium-des ...

  6. 【FICO系列】SAP FICO 凭证错误:BKPFF$PRDCLN800在FI中达到的项目最大编号

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[FICO系列]SAP FICO 凭证错误:BK ...

  7. Python3 字符编码到底是个什么鬼

    首先ASCII码是美国人自己给自己用的,只针对英文及一系列符号,凭想象预留了编码位置,不料有个东方大国文字过于复杂,预留根本不够,所以这个大国重新搞了个编码gb2312.gbk等,结果就是全世界各国都 ...

  8. argparse命令行传参

    import argparse parser = argparse.ArgumentParser(description='manual to this script') # 创建解析器,及其描述 p ...

  9. docker私有仓库-harbor

    简单说一下Harbor的部署,踩了几个坑,参考同事大神的配置文件,一脸懵逼的部署出来了,其中部分内容参考了网上一些大神的文档,本篇文章仅供参考学习,如有雷同,万分荣幸. 这篇文档仅限于centos7参 ...

  10. 第八周zuoye

    这个作业属于那个课程 C语言程序设计II 这个作业要求在哪 https://edu.cnblogs.com/campus/zswxy/computer-scienceclass3-2018/homew ...