题目大意:给定一棵 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的更多相关文章

  1. hihocoder 1035 : 自驾旅行 III

    描述 给定一棵含有 n 个结点的树,结点从 1 标号.你从 1 号结点驾车出发,希望遍历一些关键结点(访问到就好,不需要按照这些关键结点的输入顺序).每条边有两个权值,c0, c1 分别表示步行和驾车 ...

  2. 用Kotlin开发Android应用(III):扩展函数和默认值

    这是关于Kotlin的第三篇. 原文标题:Kotlin for Android (III): Extension functions and default values 原文链接:http://an ...

  3. LeetCode Single Number I / II / III

    [1]LeetCode 136 Single Number 题意:奇数个数,其中除了一个数只出现一次外,其他数都是成对出现,比如1,2,2,3,3...,求出该单个数. 解法:容易想到异或的性质,两个 ...

  4. BZOJ 3531: [Sdoi2014]旅行 [树链剖分]

    3531: [Sdoi2014]旅行 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1685  Solved: 751[Submit][Status] ...

  5. 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 ...

  6. vijos P1780 【NOIP2012】 开车旅行

    描述 小\(A\)和小\(B\)决定利用假期外出旅行,他们将想去的城市从\(1\)到\(N\)编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市\(i\)的海拔高度为 ...

  7. 【BZOJ-1570】BlueMary的旅行 分层建图 + 最大流

    1570: [JSOI2008]Blue Mary的旅行 Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 388  Solved: 212[Submit ...

  8. 【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 ...

  9. codevs 1036 商务旅行(Targin求LCA)

    传送门 Description 某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间. 假设有N个城镇,首都编号为1,商人从首都出发,其他各城镇之间都有道路连接,任意 ...

随机推荐

  1. JavaScript基础入门04

    目录 JavaScript 基础入门04 JavaScript 对象 介绍 关于键名 对象的引用 语句和表达式需要注意的地方 对象属性常见的操作 with语句 JSON 特点 语法规则 JSON合法示 ...

  2. nvm 安装及操作 node版本管理

    安装 > curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.1/install.sh | bash 安装完成后重启下 ...

  3. 【.NET】ASP.Net IE10+ SCRIPT:XXX_doPostBack 未定义

    问题描述 GridView中分页控件,点击分页无反应,Linkbutton点击无反应,打开Web控制台,发现如下错误:SCRIPTXXX:_doPostBack 未定义:查询后得知,是由于.NET F ...

  4. android4.2 webkit 中的jni

    在android 应用开发中使用WebView,当一个webveiw 被创建时, 也会去load 他所对应的动态库,这里动态库也就是传说中的webkit 内核等. C++ 层与java 层的交互也是通 ...

  5. sql server如何精准匹配字符中的字符,绝对匹配

    举例: 我现在是需要查询这字段里包含1的数据  我如果直接charindex,那么11,12也会被包含. 解决(1): select * from ( select '1,2,12,111' as s ...

  6. java 问题汇总

    1.自动加载出错 require a bean of .... The injection point has the following annotations: - @org.springfram ...

  7. Redis之面试题总结

    缓存雪崩 缓存穿透 缓存与数据库双写一致 最后 随着系统访问量的提高,复杂度的提升,响应性能成为一个重点的关注点.而缓存的使用成为一个重点.redis 作为缓存中间件的一个佼佼者,成为了面试必问项目. ...

  8. 解决postgresql数据库localhost可以连接,ip连接不了的问题

    解决:windows环境下,postgresql数据库,localhost可以连接,ip地址连接不了. 解决办法: 1.打开postgresql安装目录下的配置文件 pg_hba.conf       ...

  9. electron localStorage的bug

    在更新 electron 后有可能会读不到 localStorage 里的数据 推测是 localStorage 写在 Chromium 内核里,更新 electron 同时会更新 Chromium, ...

  10. PL/SQL Developer13安装教程

    参考: https://blog.csdn.net/qs17809259715/article/details/88855617