Ybtoj 树形DP课堂过关例题3最长距离
Posted SSL_ZZL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Ybtoj 树形DP课堂过关例题3最长距离相关的知识,希望对你有一定的参考价值。
Link
Ybtoj【树形DP课堂过关】【例题3】最长距离
题面//因为不知道侵不侵权所以就是题面是私密的,有账号的直接看转送门就可了
题目大意
给出一棵带边权的树,问每个点到最远距离点的距离
解题思路
到最远距离点,一共两种情况,向下 或 向上再向下
设 f[i][0] 为向下走的最远距离,f[now][0] = max(f[now][0], f[a[i].to][0])
向上再向下也不难办,设 f[i][2] 为向上再向下的最远距离
先求出父节点,才能求子节点,不过就是先做当前,再dfs(a[i].to)
f[a[i].to][2] = max(f[a[i].to][2],f[now][0])
BUT
如果a[i].to就在now的最长路径上呢?不就重复走了吗
设 f[i][1] 为向下走的次远距离
再拿一个数组记录一下每个点的最远距离路径走的是哪个子节点
如果当前点是 最远距离路径 上的点,那就用f[now][1],不然就用f[now][0]
Code
#include <bits/stdc++.h>
#define N 10100
using namespace std;
struct DT{
int to, s, next;
}a[N];
int n, num, y, s, head[N], f[N][3], maxn[N];
void add(int x, int y, int s) {
a[++num] = (DT){y, s, head[x]};
head[x] = num;
}
void dfs(int x) {
int mx0 = 0, mx1 = 0;
for(int i = head[x]; i; i = a[i].next){
dfs(a[i].to);
if(f[a[i].to][0] + a[i].s > mx0) {
maxn[x] = a[i].to;
mx1 = mx0, mx0 = f[a[i].to][0] + a[i].s;
} else if(f[a[i].to][0] + a[i].s > mx1)
//f[][0]创造的价值比f[][1]高;如果f[][0]比mx1小,那f[][1]肯定比mx1小。所以只比较f[][0]就好了
mx1 = f[a[i].to][0] + a[i].s;
}
f[x][0] = mx0, f[x][1] = mx1;
}
void dfs2(int x) {
for(int i = head[x]; i; i = a[i].next) {
if(a[i].to == maxn[x])
f[a[i].to][2] = max(f[x][1], f[x][2]) + a[i].s;
else f[a[i].to][2] = max(f[x][0], f[x][2]) + a[i].s;
dfs2(a[i].to);
}
}
int main() {
while(scanf("%d", &n) != EOF){ //多组数据[怒][怒][怒]
memset(head, 0, sizeof(head));
num = 0, f[1][0] = f[1][1] = f[1][2] = 0;
for(int i = 2; i <= n; i++) {
scanf("%d %d", &y, &s);
add(y, i, s);
f[i][0] = f[i][1] = f[i][2] = 0;
}
dfs(1);
dfs2(1);
for(int i = 1; i <= n; i++)
printf("%d\\n", max(f[i][0], f[i][2])); //要么向下,要么向上再向下
}
}
以上是关于Ybtoj 树形DP课堂过关例题3最长距离的主要内容,如果未能解决你的问题,请参考以下文章
luogu P1352ybtoj 树形DP课堂过关 例题1树上求和 & 没有上司的舞会
luogu UVA10559 ybtoj 区间DP课堂过关 例题3消除木块 & 方块消除 Blocks