描述

给定一棵含有 n 个结点的树,结点从 1 标号。你从 1 号结点驾车出发,希望遍历一些关键结点(访问到就好,不需要按照这些关键结点的输入顺序)。每条边有两个权值,c0, c1 分别表示步行和驾车经过这条边的代价。每次你可以选择驾车经过一条边(当且仅当有车),或者将车停放在当前所在的结点(如果有车),步行经过一条边。

求遍历完所有关键结点的最少代价。

注意: 你可以在任意结点结束遍历,即使当前没有车。

解题报告:

用时:2h20min,1RE1WA

这题做的不是很好,首先看到题目思考了许久找不到好一点的状态,然后参考了题解的状态

\(f[x][0/1/2/3/4]\)表示x子树内所有的关键点都已经走完的5中状态的最小代价

\(f[x][0]\)表示只考虑人走,且人必须回到x的最小代价

\(f[x][1]\)表示只考虑人走,且人可以不回来的最小代价(用于f[x][4]的转移)

\(f[x][2]\)表示人车一起走,且两者都回来的最小代价

\(f[x][3]\)表示人车一起走,且人回车不回的最小代价(用于f[x][4]的转移)

\(f[x][4]\)表示人车一起走,最后两者都不回来的最小代价

在自己做的时候并没有定义到\(f[x][3]\)这个状态,然后发现\(f[x][4]\)是可以借助\(f[x][3]\)转移的

设\(dis\)为该边人走的代价,\(dis0\)为车走的代价,\(u\)为x的子节点

\(f[x][0]=\sum_{u}f[u][0]+2*dis\)

\(f[x][2]=\sum_{u}Min(f[u][2]+2*dis0,f[u][0]+2*dis)\)

这两个比较显然,对于\(f[x][2]\)你可以带着车一起走完回来,也可以把车放在原地,走完回来

设\(t=(f[u][2]+2*dis0,f[u][0]+2*dis)\)

\(f[x][1]\)就是某一个子节点走的是\(f[u][1]+dis\),其他节点走的是\(t\)

\(f[x][3]\)同理,某一个点走\(f[u][3]+dis+dis0\),其他点走\(t\)

显然这两个节点的特殊节点的选择都是选择贡献最大的,即\(f[u][1]+dis\)和\(f[u][0]+dis*2\)做差后最大的一个

对于\(f[x][4]\)两者都不回,我们要分情况讨论:

1.在遍历最后一颗子树时,有车

显然遍历之前是\(f[x][3]\),然后可以选择最后一颗子树是开车还是不开车对应\(f[u][1]\)和\(f[u][4]\)

2.若此时没有车

遍历之前状态是\(f[x][2]\),其中某个子树是\(f[u][3]\),表示车没有回来人回来了,然后和上面一种情况不同的是:只能选择人走了,那么就是在不同于选择了\(f[u][3]\)的子树中再选择一个走\(f[v][1]\)

一个我没注意到的细节:

如果u同于v,那么应该记录一个次小值,不然就会少一组转移

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define RG register
#define il inline
#define iter iterator
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
const int N=1e6+5;
int head[N],num=0,to[N<<1],nxt[N<<1],dis[N<<1],dis0[N<<1];
void link(int x,int y,int d,int d0){
nxt[++num]=head[x];to[num]=y;dis[num]=d;
dis0[num]=d0;head[x]=num;
}
int gi(){
int str=0;char ch=getchar();
while(ch>'9' || ch<'0')ch=getchar();
while(ch>='0' && ch<='9')str=(str<<1)+(str<<3)+ch-48,ch=getchar();
return str;
}
int n,m;bool vis[N],mark[N];ll f[N][5];
void dfs(int x,int last){
int u,imp;ll t,f1=0,f2=0,f3=0,tmp,f4=0;
mark[x]=vis[x];
for(int i=head[x];i;i=nxt[i]){
u=to[i];if(u==last)continue;
dfs(u,x);
mark[x]+=mark[u];
if(!mark[u])continue;
f[x][0]+=f[u][0]+(dis[i]<<1);
t=Min(f[u][2]+(dis0[i]<<1),f[u][0]+(dis[i]<<1));
f[x][2]+=t;
f1=Min(f1,f[u][1]-f[u][0]-dis[i]);
tmp=f[u][3]+dis[i]+dis0[i]-t;
if(tmp<f2){
f4=f2;
f2=tmp;
imp=u;
}
else if(tmp<f4)f4=tmp;
f3=Min(f3,min(f[u][4]+dis0[i],f[u][1]+dis[i])-t);
}
f[x][1]=f[x][0]+f1;
f[x][3]=f[x][2]+f2;
f[x][4]=f[x][2]+f3;
f[x][4]=Min(f[x][4],f[x][3]);
for(int i=head[x];i;i=nxt[i]){
u=to[i];if(u==last || !mark[u])continue;
t=Min(f[u][2]+(dis0[i]<<1),f[u][0]+(dis[i]<<1));
tmp=f[u][1]+dis[i]-t;
if(u==imp)
f[x][4]=Min(f[x][4],f[x][2]+tmp+f4);
else f[x][4]=Min(f[x][4],f[x][2]+tmp+f2);
}
}
void work()
{
int x,y,d,d0;
n=gi();
for(int i=1;i<n;i++){
x=gi();y=gi();d=gi();d0=gi();
link(x,y,d,d0);link(y,x,d,d0);
}
m=gi();
for(int i=1;i<=m;i++){
x=gi();vis[x]=true;
}
dfs(1,1);
printf("%lld\n",Min(f[1][4],f[1][0]));
} int main()
{
work();
return 0;
}

hihocoder 1035 : 自驾旅行 III的更多相关文章

  1. 【hiho1035】自驾旅行III

    题目大意:给定一棵 N 个节点的有根树,1 号节点为根节点,树边有两个权值,分别为走路的代价和开车的代价.有一个旅行者开车要从根节点出发,必须遍历给定点集,可以在任何位置停止旅行,有车时可以选择开车或 ...

  2. Hihocoder 1035 [树形dp]

    /* 题意: 不要低头,不要放弃,不要气馁,不要慌张. PS:人生第一道自己独立做出来的树形dp... 给一棵树,标号1到n,每条边有两个权值,步行时间和驾车时间.车在1号点. 给m个必须访问的关键点 ...

  3. hihocoder 1075 : 开锁魔法III

    描述 一日,崔克茜来到小马镇表演魔法. 其中有一个节目是开锁咒:舞台上有 n 个盒子,每个盒子中有一把钥匙,对于每个盒子而言有且仅有一把钥匙能打开它.初始时,崔克茜将会随机地选择 k 个盒子用魔法将它 ...

  4. HihoCoder 1075 开锁魔法III(概率DP+组合)

    描述 一日,崔克茜来到小马镇表演魔法. 其中有一个节目是开锁咒:舞台上有 n 个盒子,每个盒子中有一把钥匙,对于每个盒子而言有且仅有一把钥匙能打开它.初始时,崔克茜将会随机地选择 k 个盒子用魔法将它 ...

  5. 【整理】简单的数学期望和概率DP

    数学期望 P=Σ每一种状态*对应的概率. 因为不可能枚举完所有的状态,有时也不可能枚举完,比如抛硬币,有可能一直是正面,etc.在没有接触数学期望时看到数学期望的题可能会觉得很阔怕(因为我高中就是这么 ...

  6. Hihocoder 1561 观光旅行(启发式合并+贪心)

    题目链接 Hihocoder 1561 首先对原图求$MST$ 我们发现某条边成为某两个点的关键路径的必要条件是这条边是最小生成树的树边. 所以我们求$MST$的同时进行启发式合并. 把$size$小 ...

  7. hihocoder 编程练习赛23

    第一题:H国的身份证号码I 题意:一个N位的正整数(首位不能是0).每位数字都小于等于K,并且任意相邻两位数字的乘积也小于等于K.按从小到大的顺序输出所有合法的N位号码,每个号码占一行. 思路:dfs ...

  8. hihocoder -1121-二分图的判定

    hihocoder -1121-二分图的判定 1121 : 二分图一•二分图判定 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 大家好,我是小Hi和小Ho的小伙伴Net ...

  9. Hihocoder 太阁最新面经算法竞赛18

    Hihocoder 太阁最新面经算法竞赛18 source: https://hihocoder.com/contest/hihointerview27/problems 题目1 : Big Plus ...

随机推荐

  1. scrapy爬虫框架教程(二)-- 爬取豆瓣电影TOP250

    scrapy爬虫框架教程(二)-- 爬取豆瓣电影TOP250 前言 经过上一篇教程我们已经大致了解了Scrapy的基本情况,并写了一个简单的小demo.这次我会以爬取豆瓣电影TOP250为例进一步为大 ...

  2. MySql数据库的常用命令

    1.连接Mysql 连接本地的mysql数据库 :   mysql -u root -p    (回车之后会提示输入密码) 连接远程主机的mysql数据库 : 假设远程主机的IP为:110.110.1 ...

  3. 关于移动web教程免费发布

    各位老铁大家好,最近经历了太多太多,精力一直不能集中做自己愿意做的事情. 移动Web课程一开始设置收费10块,其实本意是让大家感觉有支出,就会相对珍惜好好学习,但是发现收费把大部分人挡在门外,现在恢复 ...

  4. 14-TypeScript简单工厂模式

    在TypeScript中,要调用功能,通常在调用方通过实例化被调用方对象来调用相关方法,但这种实现在调用方和被调用方形成了强耦合的关系. 另外如果被调用方有种实现,在调用方需要根据场景去实例化不同的类 ...

  5. 微信公众号Markdown编辑器, 适合代码排版

    随着大家都转战微信公众平台,如何快速的编写文章就摆在了首要位置.不可否认,使用微信自带的编辑器可以做出好看的排版,甚至用第三方编辑器有更多的模板.但是,这些全部都需要手动的调整.本来公众平台就算是自媒 ...

  6. H5 音频标签自定义样式修改以及添加播放控制事件

    说明: 需求要求这个音频标签首先要是可适配移动端浏览器的,音频样式就是参考微信做的. 最终效果如下: 具体实现 思路: H5 的 <audio> 标签是由浏览器负责实现默认样式的.所以不同 ...

  7. 深度学习之 mnist 手写数字识别

    深度学习之 mnist 手写数字识别 开始学习深度学习,先来一个手写数字的程序 import numpy as np import os import codecs import torch from ...

  8. WPF 自定义DataGrid控件样式

    内容转自https://www.cnblogs.com/xiaogangqq123/archive/2012/05/07/2487166.html 一.DataGrid基本样式(一) 小刚已经把Dat ...

  9. Spring Boot面试题

    Spring Boot 是微服务中最好的 Java 框架. 我们建议你能够成为一名 Spring Boot 的专家. 问题一 Spring Boot.Spring MVC 和 Spring 有什么区别 ...

  10. 关于HTML

    我的PHP学习之旅 学习PHP已经有一段时间了,今天才想好好的总结一下这一路走来的点点滴滴,也想把我的学习方法及经验分享给大家,希望能对你有所帮助. 首先学习的是PHP前端部分,这里需要学习的知识有H ...