hiho_1050_树中的最长路
题目大意
给出一棵树,其中每两个节点都可以形成一个路径(要求路径中的边只能走一次),求出所有路径中的长度最大值。
分析
树形结构,很容易想到递归,但为了节省时间,要考虑保存中间状态。于是,考虑使用记忆化搜索(也就是树形动态规划)。
保存状态 dp[i][2],其中dp[i][0]表示以i为根的子树中路径的两个端点均不位于i的路径的最长值,dp[i][1]表示以i为根的子树中有一个端点位于i的路径的最长值。然后进行状态推演,
dp[root][1] = 1 + max(dp[child][1]);
dp[root][0] = max(max(max0, 2 + max1 + max2);(root的子节点数大于1)
dp[root][0] = 1 + max1;(root的子节点数等于1)
max0表示i的所有子节点中的最大的dp[c][0], max1表示i的所有字节点中最大的dp[c][1], max2表示i的所有子节点中第二大的dp[c][1].
由于树的任何一个节点均可以作为根节点,因此dfs时候,选择1即可。
实现
#pragma once
#pragma execution_character_set("utf-8")
// 本文件为utf-8 编码格式 #include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
#define N 100005
int dp[N][2];
struct Edge{
int to;
int next;
};
Edge gEdges[2*N];
int gHead[N];
bool gVisited[N];
int gEdgeIndex;
void InsertEdge(int u, int v){
int e = gEdgeIndex++;
gEdges[e].to = v;
gEdges[e].next = gHead[u];
gHead[u] = e; e = gEdgeIndex++;
gEdges[e].to = u;
gEdges[e].next = gHead[v];
gHead[v] = e;
} pair<int, int> dfs(int root){
if (dp[root][0] != -1 && dp[root][1] != -1){
return pair<int, int>(dp[root][0], dp[root][1]);
}
gVisited[root] = true;
int e = gHead[root];
int max1 = 0, max2 = 0, max = 0, child_num = 0;
for (; e != -1; e = gEdges[e].next){
int v = gEdges[e].to;
if (!gVisited[v]){
pair<int, int> result = dfs(v);
max = max > result.first ? max : result.first;
if (max1 >= result.second){
max2 = max2 > result.second ? max2 : result.second;
}
else{//求一组数中的第一大和第二大的数!!! 注意次序
/*
//这样做,在处理第一个result的时候, max1和max2赋值为同一个...error
max1 = result.second;
max2 = max1; //这样做,考虑到第一个值的处理,但是 对max1和max2的更新次序错了。 仔细考虑...
max1 = result.second;
if(max1 != 0)
max2 = max1;
*/
if (max1 != 0)
max2 = max1;
max1 = result.second;
}
child_num++;
}
}
if (child_num == 0)
dp[root][0] = dp[root][1] = 0;
else if (child_num == 1){
dp[root][0] = max;
dp[root][1] = 1 + max1;
}
else{
dp[root][1] = 1 + max1;
dp[root][0] = max > (2 + max1 + max2) ? max : (2 + max1 + max2);
} return pair<int, int>(dp[root][0], dp[root][1]);
} void Init(){
memset(gVisited, false, sizeof(gVisited));
memset(gHead, -1, sizeof(gHead));
gEdgeIndex = 0;
memset(gEdges, -1, sizeof(gEdges));
memset(dp, -1, sizeof(dp));
}
int main(){
int n, u, v;
scanf("%d", &n);
Init();
for (int i = 1; i < n; i++){
scanf("%d %d", &u, &v);
InsertEdge(u, v);
}
pair<int, int> result = dfs(1);
printf("%d\n", result.first>result.second ? result.first : result.second);
return 0;
}
hiho_1050_树中的最长路的更多相关文章
- hiho #1050 : 树中的最长路 树的直径
#1050 : 树中的最长路 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上回说到,小Ho得到了一棵二叉树玩具,这个玩具是由小球和木棍连接起来的,而在拆拼它的过程中, ...
- hihocoder 1050 树中的最长路(动态规划,dfs搜索)
hihocoder 1050 树中的最长路(动态规划,dfs搜索) Description 上回说到,小Ho得到了一棵二叉树玩具,这个玩具是由小球和木棍连接起来的,而在拆拼它的过程中,小Ho发现他不仅 ...
- hihocoder#1050 : 树中的最长路(树中最长路算法 两次BFS找根节点求最长+BFS标记路径长度+bfs不容易超时,用dfs做TLE了)
#1050 : 树中的最长路 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上回说到,小Ho得到了一棵二叉树玩具,这个玩具是由小球和木棍连接起来的,而在拆拼它的过程中, ...
- [HIHO] 1050 树中的最长路
#1050 : 树中的最长路 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上回说到,小Ho得到了一棵二叉树玩具,这个玩具是由小球和木棍连接起来的,而在拆拼它的过程中, ...
- HihoCoder第十一周:树中的最长路
#1050 : 树中的最长路 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上回说到,小Ho得到了一棵二叉树玩具,这个玩具是由小球和木棍连接起来的,而在拆拼它的过程中, ...
- hihoCoder 1050 树中的最长路 最详细的解题报告
题目来源:树中的最长路 解题思路:枚举每一个点作为转折点t,求出以t为根节点的子树中的‘最长路’以及与‘最长路’不重合的‘次长路’,用这两条路的长度之和去更新答案,最终的答案就是这棵树的最长路长度.只 ...
- 题解报告:hihoCoder #1050 : 树中的最长路
描述 上回说到,小Ho得到了一棵二叉树玩具,这个玩具是由小球和木棍连接起来的,而在拆拼它的过程中,小Ho发现他不仅仅可以拼凑成一棵二叉树!还可以拼凑成一棵多叉树——好吧,其实就是更为平常的树而已. 但 ...
- hihoCoder week11 树中的最长路
题目链接: https://hihocoder.com/contest/hiho11/problem/1 求树中节点对 距离最远的长度 #include <bits/stdc++.h> u ...
- HihoCoder1050 树中的最长路 树形DP第三题(找不到对象)
题意:求出的树中距离最远的两个结点之间相隔的距离. 水题一道,以前只会用路的直径来解. 代码如下: #include<cstdio> #include<cstdlib> #in ...
随机推荐
- reactor模式学习
一.介绍reactor模式 二.使用reactor模式 三.参考 http://blog.csdn.net/swordmanwk/article/details/6170995 该文章,简单介绍了r ...
- js九九乘法表
<!doctype html><html><head><meta charset="utf-8"><title>无标题文 ...
- 手把手教你修改iOS版QQ的运动步数
手把手教你修改iOS版QQ的运动步数 现在很多软件都加上了运动模块,比如QQ和微信,而且还有排行榜,可以和好友比较谁的运动步数多,任何东西只要添加了比较功能,就变得不一样了.今天教大家用代码去修改QQ ...
- #ifdef _DEBUG
#ifdef _DEBUG virtual void AssertValid() const; //assert(断言)valid(有效的,正确的) virtual void Dump(CDumpCo ...
- C语言中的结构体,结构体数组
C语言中的结构体是一个小难点,下面我们详细来讲一下:至于什么是结构体,结构体为什么会产生,我就不说了,原因很简单,但是要注意到是结构体也是连续存储的,但要注意的是结构体里面类型各异,所以必然会产生内存 ...
- Web的Ajax应用开发模式(一)——了解Ajax的使用形式
寄语: 前天在查看一些公司的招聘要求时,看到有公司要求测试人员了解Ajax,故写此博文旨在帮助测试人员提高自身技术知识水平,愿与广大测试同胞共同进步.(欢迎纠错!!!) 图1: 图2:
- SqlSever基础 delete 删除符合特定条件的元素
y 镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.---------------------------------------- ...
- 动手动脑final
1.回答问题 1. 下边的程序运行结果是什么? 2. 你如何解释会得到这样的输出? 3. 计算机是不会出错的,之所以得到这样的运行结果也是有原因的,那么从这些运行结果中,你能总结出Java的哪 ...
- Java_JDK_TreeMap
(一)TreeMap TreeMap使用的是红黑树来实现的,所以重点是红黑树的插入和删除. 红黑树的3个特性: 根节点和所有外部节点的颜色都是黑色的: 从根节点到外部节点的途中没有连续两个节点的颜色是 ...
- gitlab配置和搭建 ssh
(1)查看自己之前是否生成过ssh密钥: cat ~/.ssh/id_rsa.pub 如果出现一段ssh-rsa开头的,表示已经生成了,可以跳过此步骤: (2)如果之前没有生成ssh密钥,使用命令: ...