题目大意

给出一棵树,其中每两个节点都可以形成一个路径(要求路径中的边只能走一次),求出所有路径中的长度最大值。

分析

树形结构,很容易想到递归,但为了节省时间,要考虑保存中间状态。于是,考虑使用记忆化搜索(也就是树形动态规划)。 
保存状态 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赋值为同一个...errormax1 = 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_树中的最长路相关推荐

  1. 树的直径,树的最长路dp思想

    dp一直弱死了,树型dp很多基本的题都不会,最近在刷树型dp的题,把关于树的最长路的思想总结一下: 树的直径:树中距离最远的两点间的距离. 下面说几道题: hdu 2196:对于树上(双向边)的每一个 ...

  2. *【HDU - 6201】transaction transaction transaction(树形dp 或 spfa最长路 或 网络流)

    题干: 题目大意: 给出一棵n个顶点的树,每个点有一个权值,代表商品的售价,树上每一条边上也有一个权值,代表从这条边经过所需要的花费.现在需要你在树上选择两个点,一个作为买入商品的点,一个作为卖出商品 ...

  3. POJ - 3160 Father Christmas flymouse DAG最长路

    又来做这一道缩点的裸题,发现图转化为DAG后明显是一个最长路,那么有没有固定都求法呢,查询资料后发现的确是一种固定的做法. DAG最长路,分为两种固定终点和不固定终点. 令dp[i]表示从i顶点出发能 ...

  4. UVA 103 Stacking Boxes 套箱子 DAG最长路 dp记忆化搜索

    题意:给出几个多维的箱子,如果箱子的每一边都小于另一个箱子的对应边,那就称这个箱子小于另一个箱子,然后要求能够套出的最多的箱子. 要注意的是关系图的构建,对箱子的边排序,如果分别都小于另一个箱子就说明 ...

  5. hdu 1224 最长路

    开始用dijkstra直接求,发现不行,算法问题(1-2,(30),2-4(20),1--3(10),3--4(100)最后一个点无法更新,导致错误),后用取负,加大数法也没过. 现在(寒假了):求负 ...

  6. POJ3160强连通+spfa最长路(不错)

    题意:       给你一个有向图,每个点上有一个权值,可正可负,然后给你一些链接关系,让你找到一个起点,从起点开始走,走过的边可以在走,但是拿过权值的点就不能再拿了,问最多能拿到多少权值? 思路: ...

  7. 算法提高课-图论-单源最短路的建图方式-AcWing 1126. 最小花费:dijkstra求最长路

    题目分析 来源:acwing 分析: 链条转移:start * (1-w1) * (1- w2) * (1- w3) -(1-wn) = 100,要start最小,则w =(1-w1) * (1- w ...

  8. nyoj 10 skiing(DAG上的最长路,备忘录方法)

    skiing 时间限制:3000 ms  |  内存限制:65535 KB 难度:5 描述 Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑 ...

  9. 洛谷P2462 [SDOI2007]游戏(哈希+最长路)

    题面 传送门 题解 我们把字符的出现次数哈希起来,然后把每个点向能在它之后的点连边.那么这显然是一个\(DAG\),直接求最长路就行了 //minamoto #include<bits/stdc ...

最新文章

  1. 【UML】状态图Statechart diagram(转)
  2. 创新实训个人记录:approximation factor, maximum matchingvertex cover
  3. 修改了系统时间后,myeclipse 和tomcat下的代码不同步了
  4. 201209阶段二FFmpeg转码
  5. 利用ACS来实现AAA服务
  6. 4怎么修边_亦木良品阻燃板怎么样
  7. 页面头部title、description、keywords标签的优化
  8. 转行AI需要看的一些文章
  9. linux下通过gprs模块拨号上网(转)
  10. 16、document的_source元数据以及定制返回结果解析
  11. 传说中的马尔科夫链到底是个什么鬼?
  12. python语言程序设计实践教程答案实验五_Python程序设计实验五
  13. BZOJ 4816(莫比乌斯反演
  14. matlab的sinxx,用MATLAB程序编程:分析方程f(x)=sinx-x/2=0正根的分布情况,并用二分法求正根近似值,使误差不超过0.01....
  15. 【EXCEL VBA】自学心得
  16. web前端从学习到学废
  17. 开机动画启动 android 9.0
  18. js实现局部打印,并处理浏览器提示Avoid using document.write()导致无法打印问题
  19. 关于数据的封包发送和拆包使用
  20. 华为手机如何进行ADB调试

热门文章

  1. 有计算机二级证书当兵有好处吗,大学生拿到这个证书可享受的福利,当兵有什么不一样?...
  2. b区计算机考研招不满的大学,b区考研招不满的大学,适合调剂的学校有哪些
  3. python manager详解_Python通过Manager方式实现多个无关联进程共享数据
  4. python交叉编译第三方库_第三方库交叉编译
  5. FPGA之道(31)VHDL编写注意事项
  6. 小忆《记录博客一周年》
  7. 浅析FPGA时序相关问题
  8. hive无法执行带where语句的SQL
  9. 《Android应用开发》——1.3节配置Eclipse
  10. 《从缺陷中学习C/C++》——6.18 小结