【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,商人从首都出发,其他各城镇之间都有道路连接,任意 ...
随机推荐
- 利用delve(dlv)在Visual Code中进行go程序的远程调试-debug方式
最近碰到一个问题,如何在Windows的IDE或者文本编辑器上,远程调试Linux服务器上的golang程序. 虽然想说gdb走你,但既然go有dlv这样的类似Java的jdwp的原生方案,而且我用的 ...
- Python爬虫学习==>第六章:爬虫的基本原理
学习目的: 掌握爬虫相关的基本概念 正式步骤 Step1:什么是爬虫 请求网站并提取数据的自动化程序 Step2:爬虫的基本流程 Step3:Request和Response 1.request 2. ...
- PJzhang:微软出口管制条例
猫宁!!! 翻译:PJzhang 微软公司的技术,产品和服务受美国出口管理法规(EAR)的约束,由美国商务部工业与安全局(BIS)监督执行. 此外,财政部,国务院对其他与出口相关的技术和产品转让,交易 ...
- PJzhang:URL重定向漏洞的72般变化
猫宁!!! 反射型xss的利用可以给对方发送钓鱼链接,窃取对方cookie,进入对方账户. 利用url重定向漏洞,发送给对方一个钓鱼链接,重定向到一个恶意网页,比如一个假的银行网站,被盗取账号密码 ...
- 【Linux开发】linux设备驱动归纳总结(五):2.操作硬件——IO内存
linux设备驱动归纳总结(五):2.操作硬件--IO内存 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...
- n=C(2,n)+k(构造)( Print a 1337-string)Educational Codeforces Round 70 (Rated for Div. 2)
题目链接:https://codeforc.es/contest/1202/problem/D 题意: 给你一个数 n ( <=1e9 ),让你构造137713713.....(只含有1,3,7 ...
- Linux-1.1root初始密码设置,切换root用户
Ubuntu安装好后,root密码需要自己设置 root初始密码设置 sudo passwd root 权限不够时,切换root su 回车后输入密码 exit 退出登录的账户
- Docker 数据卷与容器互联
Docker是基于Go语言实现的开源容器项目,Docker让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制, ...
- 从尾到头打印列表——牛客剑指offer
题目描述 输入一个链表,按链表值从尾到头的顺序返回一个ArrayList. 解题思路 思路1: 顺序遍历链表,取出每个结点的数据,插入list中. 由于要求list倒序存储链表中的数据,而我们是顺序取 ...
- 第二篇 jQuery 选择器
2-1,2 table隔行变色 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "h ...