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;
}
时间: 2024-10-26 20:05:57

hiho_1050_树中的最长路的相关文章

HihoCoder #1050 树中的最长路

#1050 : 树中的最长路 Time Limit:10000ms Case Time Limit:1000ms Memory Limit:256MB 描述 上回说到,小Ho得到了一棵二叉树玩具,这个玩具是由小球和木棍连接起来的,而在拆拼它的过程中,小Ho发现他不仅仅可以拼凑成一棵二叉树!还可以拼凑成一棵多叉树——好吧,其实就是更为平常的树而已. 但是不管怎么说,小Ho喜爱的玩具又升级换代了,于是他更加爱不释手(其实说起来小球和木棍有什么好玩的是吧= =).小Ho手中的这棵玩具树现在由N个小球和

hiho #1050 : 树中的最长路 树的直径

#1050 : 树中的最长路 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上回说到,小Ho得到了一棵二叉树玩具,这个玩具是由小球和木棍连接起来的,而在拆拼它的过程中,小Ho发现他不仅仅可以拼凑成一棵二叉树!还可以拼凑成一棵多叉树——好吧,其实就是更为平常的树而已. 但是不管怎么说,小Ho喜爱的玩具又升级换代了,于是他更加爱不释手(其实说起来小球和木棍有什么好玩的是吧= =).小Ho手中的这棵玩具树现在由N个小球和N-1根木棍拼凑而成,这N个小球都被小Ho标上了不

hihocoder#1050 : 树中的最长路(树中最长路算法 两次BFS找根节点求最长+BFS标记路径长度+bfs不容易超时,用dfs做TLE了)

#1050 : 树中的最长路 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上回说到,小Ho得到了一棵二叉树玩具,这个玩具是由小球和木棍连接起来的,而在拆拼它的过程中,小Ho发现他不仅仅可以拼凑成一棵二叉树!还可以拼凑成一棵多叉树——好吧,其实就是更为平常的树而已. 但是不管怎么说,小Ho喜爱的玩具又升级换代了,于是他更加爱不释手(其实说起来小球和木棍有什么好玩的是吧= =).小Ho手中的这棵玩具树现在由N个小球和N-1根木棍拼凑而成,这N个小球都被小Ho标上了不

求树中的最长路 (*【模板】)

两次DFS求树中的最长路. 基于邻接矩阵: 代码: #include <stdio.h> #include <string.h> #include <vector> #include <iostream> #include <string> #include <algorithm> using namespace std; bool map[10001][10001]; int n; int tail; bool vis[1001];

hiho#1050 : 树中的最长路

#1050 : 树中的最长路 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上回说到,小Ho得到了一棵二叉树玩具,这个玩具是由小球和木棍连接起来的,而在拆拼它的过程中,小Ho发现他不仅仅可以拼凑成一棵二叉树!还可以拼凑成一棵多叉树--好吧,其实就是更为平常的树而已. 但是不管怎么说,小Ho喜爱的玩具又升级换代了,于是他更加爱不释手(其实说起来小球和木棍有什么好玩的是吧= =).小Ho手中的这棵玩具树现在由N个小球和N-1根木棍拼凑而成,这N个小球都被小Ho标上了不

树中的最长路(hihocoder 第十一周)

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上回说到,小Ho得到了一棵二叉树玩具,这个玩具是由小球和木棍连接起来的,而在拆拼它的过程中,小Ho发现他不仅仅可以拼凑成一棵二叉树!还可以拼凑成一棵多叉树——好吧,其实就是更为平常的树而已. 但是不管怎么说,小Ho喜爱的玩具又升级换代了,于是他更加爱不释手(其实说起来小球和木棍有什么好玩的是吧= =).小Ho手中的这棵玩具树现在由N个小球和N-1根木棍拼凑而成,这N个小球都被小Ho标上了不同的数字,并且这些数字都是出于

题解报告:hihoCoder #1050 : 树中的最长路

描述 上回说到,小Ho得到了一棵二叉树玩具,这个玩具是由小球和木棍连接起来的,而在拆拼它的过程中,小Ho发现他不仅仅可以拼凑成一棵二叉树!还可以拼凑成一棵多叉树--好吧,其实就是更为平常的树而已. 但是不管怎么说,小Ho喜爱的玩具又升级换代了,于是他更加爱不释手(其实说起来小球和木棍有什么好玩的是吧= =).小Ho手中的这棵玩具树现在由N个小球和N-1根木棍拼凑而成,这N个小球都被小Ho标上了不同的数字,并且这些数字都是出于1..N的范围之内,每根木棍都连接着两个不同的小球,并且保证任意两个小球

hihoCoder week11 树中的最长路

题目链接: https://hihocoder.com/contest/hiho11/problem/1 求树中节点对 距离最远的长度 #include <bits/stdc++.h> using namespace std; const int N = 1e5 + 10; int n; vector<int> G[N]; int d[N]; void dfs(int u, int fa) { for(int i=0; i<G[u].size(); i++) { int v

HihoCoder1050 树中的最长路 树形DP第三题(找不到对象)

题意:求出的树中距离最远的两个结点之间相隔的距离. 水题一道,以前只会用路的直径来解. 代码如下: #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<memory> #include<algorithm> using namespace std; const int maxn=200010; int dis[maxn],La