【hiho1035】自驾旅行III
题目大意:给定一棵 N 个节点的有根树,1 号节点为根节点,树边有两个权值,分别为走路的代价和开车的代价。有一个旅行者开车要从根节点出发,必须遍历给定点集,可以在任何位置停止旅行,有车时可以选择开车或步行,没车只能跑路,求最小代价。
题解:这是我做过最恶心的树形dp QAQ
和 apple tree 这道题很相似,只不过这次是多了车这个东西。因此,在设计状态的时候要考虑到人和车的关系,dp[u][0] 表示人走到以 u 为根的子树中必须返回的最小权值,dp[u][1] 表示人下去但是不一定上来的最小代价,dp[u][2] 表示人和车都可以下去,人和车都必须上来的最小代价,dp[u][3] 表示人和车可以下去,人上来车不一定上来的最小代价,dp[u][4] 表示人和车可以下去,但是人和车都不一定上来的最小代价。
dp[u][0-3] 的转移方程比较好想,对于最后一种情况来说,分为走最后一棵子树的时候有没有车,如果没有车就意味着在之前遍历的某棵子树中只有人回来了,因此需要考虑两棵子树对答案的贡献。可是发现,两棵子树显然不能是同一棵,因此需要记录下最优解和次优解,以及取得最优解的是哪颗子树,这样才能合并两棵子树的贡献。
代码如下
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
typedef long long LL;
int n,m,key[maxn];
LL dp[maxn][5];
struct node{int nxt,to;LL w0,w1;}e[maxn<<1]; // w0 -> walk w1 -> car
int tot=1,head[maxn];
inline void add_edge(int from,int to,LL w0,LL w1){
e[++tot]=node{head[from],to,w0,w1},head[from]=tot;
}
void dfs(int u,int fa){
LL d1=0,d3=0,d4=0;
LL fi1=1e18,se1=1e18,fi2=1e18,se2=1e18; // fi1 -> dp[v][3]+w0+w1 fi2 -> dp[v][1]+w0
int x=0,y=0;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to; LL w0=e[i].w0,w1=e[i].w1;
if(v==fa)continue;
dfs(v,u);
key[u]+=key[v];
if(key[v]){
LL t=min(dp[v][0]+2*w0,dp[v][2]+2*w1);
dp[u][0]+=dp[v][0]+2*w0;
dp[u][2]+=t;
d1=min(d1,dp[v][1]-dp[v][0]-w0);
d3=min(d3,dp[v][3]+w0+w1-t);
d4=min(d4,min(dp[v][4]+w1,dp[v][1]+w0)-t);
LL ret1=dp[v][3]+w0+w1-t;
if(ret1<fi1)se1=fi1,fi1=ret1,x=v;
else se1=min(se1,ret1);
LL ret2=dp[v][1]+w0-t;
if(ret2<fi2)se2=fi2,fi2=ret2,y=v;
else se2=min(se2,ret2);
}
}
if(x&&y){
if(x!=y)d4=min(d4,fi1+fi2);
else d4=min(d4,min(fi1+se2,fi2+se1));
}
dp[u][1]=dp[u][0]+d1;
dp[u][3]=dp[u][2]+d3;
dp[u][4]=dp[u][2]+d4;
}
void read_and_parse(){
scanf("%d",&n);
for(int i=1;i<n;i++){
int x,y,w0,w1;
scanf("%d%d%d%d",&x,&y,&w0,&w1);
add_edge(x,y,w0,w1),add_edge(y,x,w0,w1);
}
scanf("%d",&m);
for(int i=1;i<=m;i++){
int x;scanf("%d",&x);
key[x]++;
}
}
void solve(){
dfs(1,0);
printf("%lld\n",dp[1][4]);
}
int main(){
read_and_parse();
solve();
return 0;
}
【hiho1035】自驾旅行III的更多相关文章
- hihocoder 1035 : 自驾旅行 III
描述 给定一棵含有 n 个结点的树,结点从 1 标号.你从 1 号结点驾车出发,希望遍历一些关键结点(访问到就好,不需要按照这些关键结点的输入顺序).每条边有两个权值,c0, c1 分别表示步行和驾车 ...
- 用Kotlin开发Android应用(III):扩展函数和默认值
这是关于Kotlin的第三篇. 原文标题:Kotlin for Android (III): Extension functions and default values 原文链接:http://an ...
- LeetCode Single Number I / II / III
[1]LeetCode 136 Single Number 题意:奇数个数,其中除了一个数只出现一次外,其他数都是成对出现,比如1,2,2,3,3...,求出该单个数. 解法:容易想到异或的性质,两个 ...
- BZOJ 3531: [Sdoi2014]旅行 [树链剖分]
3531: [Sdoi2014]旅行 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1685 Solved: 751[Submit][Status] ...
- SPOJ GSS3 Can you answer these queries III[线段树]
SPOJ - GSS3 Can you answer these queries III Description You are given a sequence A of N (N <= 50 ...
- vijos P1780 【NOIP2012】 开车旅行
描述 小\(A\)和小\(B\)决定利用假期外出旅行,他们将想去的城市从\(1\)到\(N\)编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市\(i\)的海拔高度为 ...
- 【BZOJ-1570】BlueMary的旅行 分层建图 + 最大流
1570: [JSOI2008]Blue Mary的旅行 Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 388 Solved: 212[Submit ...
- 【Codeforces717F】Heroes of Making Magic III 线段树 + 找规律
F. Heroes of Making Magic III time limit per test:3 seconds memory limit per test:256 megabytes inpu ...
- codevs 1036 商务旅行(Targin求LCA)
传送门 Description 某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间. 假设有N个城镇,首都编号为1,商人从首都出发,其他各城镇之间都有道路连接,任意 ...
随机推荐
- PJzhang:U盘容量变小后的恢复以及U盘加密
猫宁!!! 参考链接:https://jingyan.baidu.com/article/8ebacdf0544ae049f65cd5da.html 我的一个U盘,16G,制作了deepin linu ...
- Opencv-python3.3版本安装
因为目前为止(2019.11.17)opencv最新版本为4.1,因此直接pip install opencv-python的话,无法安装想要的版本(老师推荐3.X) 上清华镜像查找opencv-py ...
- 1.2.2 OSI参考模型 上
一.HCNA网络技术学习指南 为了实现网络的互通及各种各样的网络应用,网络设备需要运行各种各样的协议已实现各种各样具体的功能.面对各种各样且数量繁多的功能,我们可以从网络架构的角度,引入功能分层的模型 ...
- webdriervAPI(多窗口切换)
两个方法 driver.current_window_handle 获取当前窗口句柄 driver.window_handles 获取所有窗口句柄 from selenium import webdr ...
- 【Python开发】python发送各类邮件的方法
转载: python发送各类邮件的主要方法 python中email模块使得处理邮件变得比较简单,今天着重学习了一下发送邮件的具体做法,这里写写自己的的心得,也请高手给些指点. 一.相关模块介绍 发送 ...
- Sql Service 存储过程、触发器
if exists (select * from sysobjects where name='tb_admin') drop table tb_admin go create table tb_ad ...
- Laravel 查询&数据库&模型
1.with()与load区别: 都称为 延迟预加载,不同点在于 load()是在已经查询出来的模型上调用,而 with() 则是在 ORM 查询构造器上调用. Order::query()-> ...
- 【Python】【基础知识】【内置函数】【help的使用方法】
原英文帮助文档: help([object]) Invoke the built-in help system. (This function is intended for interactive ...
- 从零开始,SpreadJS新人学习笔记【第3周】
表单&函数 阔别多日, SpreadJS新人学习笔记,本周起正式回归!(在断更的这一个月中,我为大家先后录制了14期SpreadJS产品入门系列学习视频,希望帮助那些正在学习和使用 Sprea ...
- 协程+IO切换+小爬虫
from gevent import monkeymonkey.patch_all() import geventimport requests def f1(url): print(f'GET:{u ...