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赋值为同一个...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_树中的最长路相关推荐
- 树的直径,树的最长路dp思想
dp一直弱死了,树型dp很多基本的题都不会,最近在刷树型dp的题,把关于树的最长路的思想总结一下: 树的直径:树中距离最远的两点间的距离. 下面说几道题: hdu 2196:对于树上(双向边)的每一个 ...
- *【HDU - 6201】transaction transaction transaction(树形dp 或 spfa最长路 或 网络流)
题干: 题目大意: 给出一棵n个顶点的树,每个点有一个权值,代表商品的售价,树上每一条边上也有一个权值,代表从这条边经过所需要的花费.现在需要你在树上选择两个点,一个作为买入商品的点,一个作为卖出商品 ...
- POJ - 3160 Father Christmas flymouse DAG最长路
又来做这一道缩点的裸题,发现图转化为DAG后明显是一个最长路,那么有没有固定都求法呢,查询资料后发现的确是一种固定的做法. DAG最长路,分为两种固定终点和不固定终点. 令dp[i]表示从i顶点出发能 ...
- UVA 103 Stacking Boxes 套箱子 DAG最长路 dp记忆化搜索
题意:给出几个多维的箱子,如果箱子的每一边都小于另一个箱子的对应边,那就称这个箱子小于另一个箱子,然后要求能够套出的最多的箱子. 要注意的是关系图的构建,对箱子的边排序,如果分别都小于另一个箱子就说明 ...
- hdu 1224 最长路
开始用dijkstra直接求,发现不行,算法问题(1-2,(30),2-4(20),1--3(10),3--4(100)最后一个点无法更新,导致错误),后用取负,加大数法也没过. 现在(寒假了):求负 ...
- POJ3160强连通+spfa最长路(不错)
题意: 给你一个有向图,每个点上有一个权值,可正可负,然后给你一些链接关系,让你找到一个起点,从起点开始走,走过的边可以在走,但是拿过权值的点就不能再拿了,问最多能拿到多少权值? 思路: ...
- 算法提高课-图论-单源最短路的建图方式-AcWing 1126. 最小花费:dijkstra求最长路
题目分析 来源:acwing 分析: 链条转移:start * (1-w1) * (1- w2) * (1- w3) -(1-wn) = 100,要start最小,则w =(1-w1) * (1- w ...
- nyoj 10 skiing(DAG上的最长路,备忘录方法)
skiing 时间限制:3000 ms | 内存限制:65535 KB 难度:5 描述 Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑 ...
- 洛谷P2462 [SDOI2007]游戏(哈希+最长路)
题面 传送门 题解 我们把字符的出现次数哈希起来,然后把每个点向能在它之后的点连边.那么这显然是一个\(DAG\),直接求最长路就行了 //minamoto #include<bits/stdc ...
最新文章
- 【UML】状态图Statechart diagram(转)
- 创新实训个人记录:approximation factor, maximum matchingvertex cover
- 修改了系统时间后,myeclipse 和tomcat下的代码不同步了
- 201209阶段二FFmpeg转码
- 利用ACS来实现AAA服务
- 4怎么修边_亦木良品阻燃板怎么样
- 页面头部title、description、keywords标签的优化
- 转行AI需要看的一些文章
- linux下通过gprs模块拨号上网(转)
- 16、document的_source元数据以及定制返回结果解析
- 传说中的马尔科夫链到底是个什么鬼?
- python语言程序设计实践教程答案实验五_Python程序设计实验五
- BZOJ 4816(莫比乌斯反演
- matlab的sinxx,用MATLAB程序编程:分析方程f(x)=sinx-x/2=0正根的分布情况,并用二分法求正根近似值,使误差不超过0.01....
- 【EXCEL VBA】自学心得
- web前端从学习到学废
- 开机动画启动 android 9.0
- js实现局部打印,并处理浏览器提示Avoid using document.write()导致无法打印问题
- 关于数据的封包发送和拆包使用
- 华为手机如何进行ADB调试
热门文章
- 有计算机二级证书当兵有好处吗,大学生拿到这个证书可享受的福利,当兵有什么不一样?...
- b区计算机考研招不满的大学,b区考研招不满的大学,适合调剂的学校有哪些
- python manager详解_Python通过Manager方式实现多个无关联进程共享数据
- python交叉编译第三方库_第三方库交叉编译
- FPGA之道(31)VHDL编写注意事项
- 小忆《记录博客一周年》
- 浅析FPGA时序相关问题
- hive无法执行带where语句的SQL
- 《Android应用开发》——1.3节配置Eclipse
- 《从缺陷中学习C/C++》——6.18 小结