【NOIP2016练习】T2 旅行(树形DP,换根)
题意:小C上周末和他可爱的同学小A一起去X湖玩。
X湖景区一共有n个景点,这些景点由n-1条观光道连接着,从每个景点开始都可以通过观光道直接或间接地走到其他所有的景点。小C带着小A从1号景点开始游玩。游览完第一个景点后,先由小C决定下一个游览的景点,他们一起走去那个景点玩。接下来,他们轮流决定他们下一步去哪个景点玩。他们不会选择已经走过的景点,因为重复游览一个景点是无趣的。当他们无法选择下一个景点时,他们就结束旅程。
小C是好动的男孩纸,所以他希望游览的过程尽量长,也就是走过观光道的长度和最大。而小A是文静的女孩纸,她希望游览的过程尽量短。小A和小C都极度聪明,且他们的目光都足够长远,他们做出的决策都是对自己最优的。由于小C在旅游前就仔细研究了X湖景区的地图,他可以在旅行开始前就用自己惊人的数学能力推算出他和小A旅行的路径长度。
小C的梦境是美好的。在他的梦里,他和小A又进行了n-1次旅行,第i次旅行从i+1号点开始,每次也是小C先决定下一个景点,然后小A,然后小C……直到旅行结束。现在小C希望你对于所有n次旅行,求出他和小A旅行的路径长度。
对于100%的数据,N ≤ 300000, c[i] ≤ 1e9
对于60%的数据,N ≤ 3000
思路:对于60分,容易想到枚举根,做N次O(N)的DP,时间复杂度O(n)
对于100分,模拟样例后发现两个直接相连的节点U与V,其DP值只有U与V点时不同,所以考虑当根从U到V时O(1)转移求出新的DP[u]与DP[v]
注意此处不需要保证整个DP数组值都为正确,只要U的值与V的值正确即可
可以想到当U的最值由V转移时,两者交换后V必须从U的另一支转移,所以记录次值
调参大法好
var f:array[..,..]of int64;
ans:array[..]of int64;
head,vet,next,len,flag:array[..]of longint;
n,tot,i,x,y,z:longint;
oo:int64; procedure add(a,b,c:longint);
begin
inc(tot);
next[tot]:=head[a];
vet[tot]:=b;
len[tot]:=c;
head[a]:=tot;
end; procedure dfs(u:longint);
var e,v,de:longint;
t:int64;
begin
flag[u]:=;
e:=head[u];
de:=;
while e<> do
begin
v:=vet[e];
if flag[v]= then
begin
dfs(v); inc(de);
t:=f[v,]+len[e];
if (t>f[u,])or(f[u,]=) then
begin
f[u,]:=f[u,]; f[u,]:=t;
end
else if (t<=f[u,])and(t>f[u,])or(f[u,]=) then f[u,]:=t; t:=f[v,]+len[e];
if (t<f[u,])or(f[u,]=) then
begin
f[u,]:=f[u,]; f[u,]:=t;
end
else if (t>=f[u,])and(t<f[u,])or(f[u,]=) then f[u,]:=t; end;
e:=next[e];
end; end; procedure change(u:longint);
var e,v:longint;
t,t1,t2,t3,t4:int64;
begin
e:=head[u]; flag[u]:=;
t1:=f[u,]; t2:=f[u,]; t3:=f[u,]; t4:=f[u,]; ans[u]:=f[u,];
while e<> do
begin
v:=vet[e]; if flag[v]= then begin e:=next[e]; continue; end;
if f[v,]+len[e]=t1 then t:=f[u,]+len[e]
else t:=f[u,]+len[e];
if (t<f[v,])or(f[v,]=) then
begin
f[v,]:=f[v,]; f[v,]:=t;
end
else if (t<f[v,])or(f[v,]=) then f[v,]:=t; if f[v,]+len[e]=t3 then begin t:=f[u,]+len[e];end
else t:=f[u,]+len[e]; if (t>f[v,])or(f[v,]=) then
begin
f[v,]:=f[v,]; f[v,]:=t;
end
else if (t>f[v,])or(f[v,]=) then f[v,]:=t;
change(v);
e:=next[e];
end; end; begin
assign(input,'travel.in'); reset(input);
assign(output,'travel.out'); rewrite(output);
oo:=<<;
readln(n); //f[u,]zuida f[u,]cida
//f[u,]zuixiao f[u,]cixiao
for i:= to n- do
begin
readln(x,y,z);
add(x,y,z);
add(y,x,z);
end; dfs();
fillchar(flag,sizeof(flag),);
change();
for i:= to n do writeln(ans[i]);
close(input);
close(output);
end.
【NOIP2016练习】T2 旅行(树形DP,换根)的更多相关文章
- bzoj 3743 [Coci2015]Kamp——树形dp+换根
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3743 树形dp+换根. “从根出发又回到根” 减去 “mx ” . 注意dfsx里真的要改那 ...
- 树形dp换根,求切断任意边形成的两个子树的直径——hdu6686
换根dp就是先任取一点为根,预处理出一些信息,然后在第二次dfs过程中进行状态的转移处理 本题难点在于任意割断一条边,求出剩下两棵子树的直径: 设割断的边为(u,v),设down[v]为以v为根的子树 ...
- poj3585 Accumulation Degree(树形dp,换根)
题意: 给你一棵n个顶点的树,有n-1条边,每一条边有一个容量z,表示x点到y点最多能通过z容量的水. 你可以任意选择一个点,然后从这个点倒水,然后水会经过一些边流到叶节点从而流出.问你最多你能倒多少 ...
- poj3585 Accumulation Degree[树形DP换根]
思路其实非常简单,借用一下最大流求法即可...默认以1为根时,$f[x]$表示以$x$为根的子树最大流.转移的话分两种情况,一种由叶子转移,一种由正常孩子转移,判断一下即可.换根的时候由頂向下递推转移 ...
- [题解](树形dp/换根)小x游世界树
2. 小x游世界树 (yggdrasi.pas/c/cpp) [问题描述] 小x得到了一个(不可靠的)小道消息,传说中的神岛阿瓦隆在格陵兰海的某处,据说那里埋藏着亚瑟王的宝藏,这引起了小x的好奇,但当 ...
- Acwing-287-积蓄程度(树上DP, 换根)
链接: https://www.acwing.com/problem/content/289/ 题意: 有一个树形的水系,由 N-1 条河道和 N 个交叉点组成. 我们可以把交叉点看作树中的节点,编号 ...
- 2019ICPC沈阳网络赛-D-Fish eating fruit(树上DP, 换根, 点分治)
链接: https://nanti.jisuanke.com/t/41403 题意: State Z is a underwater kingdom of the Atlantic Ocean. Th ...
- bzoj 1131 [POI2008]Sta 树形dp 转移根模板题
[POI2008]Sta Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1889 Solved: 729[Submit][Status][Discu ...
- cf219d 基础换根法
/*树形dp换根法*/ #include<bits/stdc++.h> using namespace std; #define maxn 200005 ]; int root,n,s,t ...
- Codeforces Round #527 (Div. 3) F. Tree with Maximum Cost 【DFS换根 || 树形dp】
传送门:http://codeforces.com/contest/1092/problem/F F. Tree with Maximum Cost time limit per test 2 sec ...
随机推荐
- python-判断alter是否存在
from selenium import webdriver import time from selenium.webdriver.support.ui import WebDriverWait f ...
- cocos2dx 加密spine文件遇到的问题(暂时没有解决方法)
今天我研究了一下加密spine动画的加密的方法,图片肯定要加密的,所以我只选择加密图片,另外的一个altas文件和json文件就不做加密打算. 我的思路是通过TexturePacker打包成加密的文件 ...
- LeetCode之Weekly Contest 91
第一题:柠檬水找零 问题: 在柠檬水摊上,每一杯柠檬水的售价为 5 美元. 顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯. 每位顾客只买一杯柠檬水,然后向你付 5 美元.10 ...
- writing a usb driver(在国外的网站上复制下来的)
Writing a Simple USB Driver From Issue #120April 2004 Apr 01, 2004 By Greg Kroah-Hartman in Soft ...
- CodeForces:148D-D.Bag of mice
Bag of mice time limit per test 2 seconds memory limit per test 256 megabytes Program Description Th ...
- hdu 6301
Distinct Values Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- SPOJ FFT TSUM
第一道FFT的题目. 在网上找了很多FFT的资料,但一直都看不懂,最后是看算法导论学的FFT,算法导论上面写的很详细,每一步推导过程都有严格的证明. 下面说这道题 题意: 给一个序列s,有n个不互相同 ...
- loj2013 「SCOI2016」幸运数字
点分治+线性基 (为了这六个字窝调了一下午一晚上QAQ #include <iostream> #include <cstring> #include <cstdio&g ...
- luogu1736 创意吃鱼法
好的题解使人一下就懂啊-- s1[i][j]表示(i,j)最多向左(或右)延伸多少个格子,使这些格子中的数都是0(不包括(i,j)) s2[i][j]表示(i,j)最多向上延伸多少个格子,使这些格子中 ...
- 剑指offer算法编程题目部分汇总(解法略)
总结一下本书中遇到的大部分面试题.面试题3:二维数组中的查找 题目:在一个二维数组中,每一行都按照从左到右的递增顺序排列,每一列都按照从上到下递增的顺序排列,请完成一个函数,输入这样的一个整数,判断数 ...