BZOJ 1509: [NOI2003]逃学的小孩( 树形dp )

树形dp求出某个点的最长3条链a,b,c(a>=b>=c), 然后以这个点为交点的最优解一定是a+2b+c.好像还有一种做法是求出树的直径然后乱搞...

---------------------------------------------------------------------

#include<cstdio>

#include<cstring>

#include<algorithm>

#include<cctype>

using namespace std;

typedef long long ll;

const int maxn = 200009;

int N;

ll X[maxn], Y[maxn], Z[maxn], F[maxn], ans;

struct edge {

int to, w;

edge* next;

} E[maxn << 1], *pt = E, *head[maxn];

void AddEdge(int u, int v, int w) {

pt->to = v;

pt->w = w;

pt->next = head[u];

head[u] = pt++;

}

inline int read() {

char c = getchar();

int ret = 0;

for(; !isdigit(c); c = getchar());

for(; isdigit(c); c = getchar()) ret = ret * 10 + c - ‘0‘;

return ret;

}

void Init() {

N = read();

int m = read();

while(m--) {

int u = read() - 1, v = read() - 1, w = read();

AddEdge(u, v, w);

AddEdge(v, u, w);

}

}

void DFS0(int x, int fa = -1) {

X[x] = Y[x] = 0;

for(edge* e = head[x]; e; e = e->next) if(e->to != fa) {

DFS0(e->to, x);

Z[x] = max(Z[x], X[e->to] + e->w);

if(Z[x] > Y[x]) swap(Z[x], Y[x]);

if(Y[x] > X[x]) swap(X[x], Y[x]);

}

}

void DFS1(int x, int fa = -1) {

for(edge* e = head[x]; e; e = e->next) if(e->to != fa) {

F[e->to] = F[x] + e->w;

if(X[e->to] + e->w == X[x])

F[e->to] = max(F[e->to], Y[x] + e->w);

else

F[e->to] = max(F[e->to], X[x] + e->w);

DFS1(e->to, x);

}

}

inline void upd(ll &x, ll &y, ll &z) {

if(y > x) swap(x, y);

if(z > x) swap(x, z);

if(z > y) swap(y, z);

ans = max(x + (y << 1) + z, ans);

}

int main() {

Init();

DFS0(0);

DFS1(F[0] = 0);

ans = 0;

for(int i = 0; i < N; i++)

F[i] <= Z[i] ? upd(X[i], Y[i], Z[i]) : upd(X[i], Y[i], F[i]);

printf("%lld\n", ans);

return 0;

}

---------------------------------------------------------------------

1509: [NOI2003]逃学的小孩

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 528  Solved: 285
[Submit][Status][Discuss]

Description

Input

第一行是两个整数N(3 ? N ? 200000)和M,分别表示居住点总数和街道总数。以下M行,每行给出一条街道的信息。第i+1行包含整数Ui、Vi、Ti(1?Ui, Vi ? N,1 ? Ti ? 1000000000),表示街道i连接居住点Ui和Vi,并且经过街道i需花费Ti分钟。街道信息不会重复给出。

Output

仅包含整数T,即最坏情况下Chris的父母需要花费T分钟才能找到Chris。

Sample Input

4 3
1 2 1
2 3 1
3 4 1

Sample Output

4

HINT

Source

时间: 2024-11-29 12:49:33

BZOJ 1509: [NOI2003]逃学的小孩( 树形dp )的相关文章

BZOJ 1509 [NOI2003]逃学的小孩

题意:给定一棵树,设A, B, C为树上的三个不相同的点,求出max{dist(A, B) + min{dist(C, A), dist(C, B)}} 首先,如果dist(A,B)最大的话,很显然这是树上的一条最长链.也就是说,A和B是树上任意一条最长链的两个端点. 然后,我们有一个结论:树上某个点的最远点必定是树上任意一条最长链的两个端点中的一个.. 综合上面两个结论我们可以得到,当dist(A, B)和min{dist(C, A), dist(C, B)}同时取最大时,都与树上的最长链有关

1509: [NOI2003]逃学的小孩 - BZOJ

Description Input 第一行是两个整数N(3 ? N ? 200000)和M,分别表示居住点总数和街道总数.以下M行,每行给出一条街道的信息.第i+1行包含整数Ui.Vi.Ti(1?Ui, Vi ? N,1 ? Ti ? 1000000000),表示街道i连接居住点Ui和Vi,并且经过街道i需花费Ti分钟.街道信息不会重复给出.Output 仅包含整数T,即最坏情况下Chris的父母需要花费T分钟才能找到Chris.Sample Input 4 3 1 2 1 2 3 1 3 4

NOI2003 逃学的小孩

这一题不会做啊-- 我觉得真要比赛的话我可能会随机上几万次,然后再用LCA求距离,更新最优值,等到快超时的时候输出答案-- 题解请看2007年陈瑜希论文 代码: 1 const maxn=400100; 2 type node=record 3 w,go,next:longint; 4 end; 5 var e:array[0..maxn] of node; 6 f:array[0..maxn,1..3] of int64; 7 first,u:array[0..maxn] of longint

BZOJ 1907 树的路径覆盖 树形DP

题目大意:给定一棵树,求最小路径覆盖 数据范围1W,看到还想跑网络流来着= = 不过算了明明树形DP这么水还是不要用网络流这种大杀器为好 首先将所有的链都考虑成以链上所有点的LCA为转折点的V字形 那么点有两种:转折点和非转折点 因此我们选择两种状态进行转移:还会和父亲组成链的状态和成为转折点的状态 转移就自己YY算了 时间复杂度是线性的 #include <cstdio> #include <cstring> #include <iostream> #include

bzoj 1017[JSOI2008]魔兽地图DotR - 树形dp

1017: [JSOI2008]魔兽地图DotR Time Limit: 30 Sec  Memory Limit: 162 MB Description DotR (Defense of the Robots) Allstars是一个风靡全球的魔兽地图,他的规则简单与同样流行的地图DotA (Defense of the Ancients) Allstars.DotR里面的英雄只有一个属性--力量.他们需要购买装备来提升自己的力量值,每件装备都可以使佩戴它的英雄的力量值提高固定的点数,所以英雄

BZOJ 3238: [Ahoi2013]差异 后缀自动机 树形dp

http://www.lydsy.com/JudgeOnline/problem.php?id=3238 就算是全局变量,也不要忘记,初始化(吐血). 长得一副lca样,没想到是个树形dp(小丫头还有两幅面孔呢). 看代码实现吧,不大容易口头解释,把加的和减的分开算就可以了,减去的通过倒着建sam(相当于建一棵后缀树),然后算每个len取的次数实现,注意树归中一些避免重复操作. 1 /********************************************************

bzoj 1060: [ZJOI2007]时态同步【树形dp】

可能算不上dp,大概是个树形模拟 先一遍dfs算出f[u]为每个点最深的叶子到u的距离,然后再dfs一下,ans加上f[u]-f[e[i].to]-e[i].va,f[u]-f[e[i].to]是这条边应该的用时 #include<iostream> #include<cstdio> using namespace std; const int N=500005; int n,m,cnt,f[N],h[N]; long long ans; struct qwe { int ne,t

BZOJ 1017 魔兽地图DotR(树形DP)

题意:有两类装备,高级装备A和基础装备B.现在有m的钱.每种B有一个单价和可以购买的数量上限.每个Ai可以由Ci种其他物品合成,给出Ci种其他物品每种需要的数量.每个装备有一个贡献值.求最大的贡献值.已知物品的合成路线是一个严格的树模型.即有一种物品不会合成其他任意物品,其余物品都会仅仅可用作合成另外一种物品 思路:f[i][j][k],代表第i个物品,花费了j,向上提供k个i物品. 1 #include<algorithm> 2 #include<cstdio> 3 #inclu

【BZOJ 3238】差异 后缀自动机+树形DP

题意 给定字符串,令$s_i$表示第$i$位开始的后缀,求$\sum_{1\le i < j \le n} len(s_i)+len(s_j)-2\times lcp(s_i,s_j)$ 先考虑前面的和式,直接计算为$\frac{n(n^2-1)}{2}$,考虑后面的和式,$lcp$相关可以用sam求解,sam形成的parent树是原串的前缀树,所以两个串的最长公共后缀是在parent树上最近公共祖先对应的状态的长度$maxlen_s-maxlen_{pa_s}$,将原串反向建立sam得到后缀树