题意:小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,换根)的更多相关文章

  1. bzoj 3743 [Coci2015]Kamp——树形dp+换根

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3743 树形dp+换根. “从根出发又回到根” 减去 “mx ” . 注意dfsx里真的要改那 ...

  2. 树形dp换根,求切断任意边形成的两个子树的直径——hdu6686

    换根dp就是先任取一点为根,预处理出一些信息,然后在第二次dfs过程中进行状态的转移处理 本题难点在于任意割断一条边,求出剩下两棵子树的直径: 设割断的边为(u,v),设down[v]为以v为根的子树 ...

  3. poj3585 Accumulation Degree(树形dp,换根)

    题意: 给你一棵n个顶点的树,有n-1条边,每一条边有一个容量z,表示x点到y点最多能通过z容量的水. 你可以任意选择一个点,然后从这个点倒水,然后水会经过一些边流到叶节点从而流出.问你最多你能倒多少 ...

  4. poj3585 Accumulation Degree[树形DP换根]

    思路其实非常简单,借用一下最大流求法即可...默认以1为根时,$f[x]$表示以$x$为根的子树最大流.转移的话分两种情况,一种由叶子转移,一种由正常孩子转移,判断一下即可.换根的时候由頂向下递推转移 ...

  5. [题解](树形dp/换根)小x游世界树

    2. 小x游世界树 (yggdrasi.pas/c/cpp) [问题描述] 小x得到了一个(不可靠的)小道消息,传说中的神岛阿瓦隆在格陵兰海的某处,据说那里埋藏着亚瑟王的宝藏,这引起了小x的好奇,但当 ...

  6. Acwing-287-积蓄程度(树上DP, 换根)

    链接: https://www.acwing.com/problem/content/289/ 题意: 有一个树形的水系,由 N-1 条河道和 N 个交叉点组成. 我们可以把交叉点看作树中的节点,编号 ...

  7. 2019ICPC沈阳网络赛-D-Fish eating fruit(树上DP, 换根, 点分治)

    链接: https://nanti.jisuanke.com/t/41403 题意: State Z is a underwater kingdom of the Atlantic Ocean. Th ...

  8. bzoj 1131 [POI2008]Sta 树形dp 转移根模板题

    [POI2008]Sta Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1889  Solved: 729[Submit][Status][Discu ...

  9. cf219d 基础换根法

    /*树形dp换根法*/ #include<bits/stdc++.h> using namespace std; #define maxn 200005 ]; int root,n,s,t ...

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

随机推荐

  1. cocos2dx 3.x for lua "异步加载"实现过程

    在lua中,cocos2dx 建立的栈只能被一个线程(主线程)访问,如果在c++建立子线程,然后通过c++调用lua回调函数实现异步加载就会报错. 如果试图通过c++子线程直接实现加载资源,返回一个布 ...

  2. sqlserver的实例名忘记了

    电脑图标右击/管理/服务和应用程序/服务 也可以直接services.msc打开 打开服务,找到sqlserver的服务,这个服务括号中的名称就是实例名了,但是要加上localhost,也就是loca ...

  3. 如何理解JavaScript中的this关键字

    前言 王福朋老师的 JavaScript原型和闭包系列 文章看了不下三遍了,最为一个初学者,每次看的时候都会有一种 "大彻大悟" 的感觉,而看完之后却总是一脸懵逼.原型与闭包 可以 ...

  4. 头文件string与string.h的区别

    在C++中,#include<iostream>与#include<iostream.h>的区别,前者要使用更新的编译器(其实大部分编译器多比较前卫了,出了有些搞嵌入式的用变态 ...

  5. 单行代码实现xml转换成数组

    $string = '<xml> <return_code><![CDATA[SUCCESS]]></return_code> <return_m ...

  6. 《零基础入门学习Python》【第一版】视频课后答案第002讲

    测试题答案: 0. 什么是BIF?BIF 就是 Built-in Functions,内置函数.为了方便程序员快速编写脚本程序(脚本就是要编程速度快快快!!!),Python 提供了非常丰富的内置函数 ...

  7. Java-downloadFileByLink

    import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.ByteArrayOutputStr ...

  8. SQL防止重复提交和Filter

    /class User package com.neuedu.bean; import java.io.Serializable; public class User implements Seria ...

  9. poj 2376 选择工作区间问题 贪心算法

    题意:给一些工作区间,如何选取最小的工作数量,覆盖[1,T]的工作时长 一开始的思路,当然也是错误的思路: 我想着,最小工作数量是吧?那肯定就是选择结束时间最晚的,给结束时间来一个排序.哎这个思路错误 ...

  10. kettle 增量同步

    http://www.cnblogs.com/inuyasha1027/p/Kettle_update_timestamp.html https://ask.hellobi.com/blog/yugu ...