[hiho 11]树的直径

题目描述

树的直径必然取自某个节点的两个(或一个)最深的子树,可以一遍DFS解决。

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

vector<int> tree[100005];
bool has_parent[100005] = { false };
int max_length[100005];
int ans;

void solve(int root_idx) {
	int lgst = 0, lgst_idx = 0;
	int size = tree[root_idx].size();
	for (int i = 0; i < size; i++) { // 递归求树深
		int sub_idx = tree[root_idx][i];
		solve(sub_idx);
		if (lgst < max_length[sub_idx]) {
			lgst = max_length[sub_idx];
			lgst_idx = i;
		}
	}
	max_length[root_idx] = lgst + 1;

	int sec_lgst = 0;
	for (int i = 0; i < size; i++) { // 次深子树深度
		int sub_idx = tree[root_idx][i];
		if (sec_lgst < max_length[sub_idx] && i != lgst_idx) {
			sec_lgst = max_length[sub_idx];
		}
	}
	ans = max(ans, lgst + sec_lgst);
}

int main() {
	int n;
	cin >> n;
	for(int i = 1; i < n; i++) {
		int a, b;
		cin >> a >> b;
		if (has_parent[a]) {
			tree[a].push_back(b);
			has_parent[b] = true;
		} else {
			tree[b].push_back(a);
			has_parent[a] = true;
		}
	}
	for (int i = 1; i <= n; i++) {
		if (!has_parent[i]) {
			solve(i);
			break;
		}
	}

	cout << ans << endl;
	return 0;
}

另一种做法是两遍BFS:以任一个节点为根BFS找到最远的节点,再从该节点BFS找到的最长路径就是直径。

#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>

using namespace std;

vector<int> tree[100005];
int length[100005];
int max_length, max_idx;

void bfs(int root_idx, int pa_idx, int depth) {
	length[root_idx] = depth;
	if (max_length < depth) {
		max_length = depth;
		max_idx = root_idx;
	}
	int len = tree[root_idx].size();
	for (int i = 0; i < len; i++) {
		int sub_idx = tree[root_idx][i];
		if (sub_idx != pa_idx) {
			bfs(sub_idx, root_idx, depth + 1);
		}

	}
}

int main() {
	int n;
	cin >> n;
	for(int i = 1; i < n; i++) {
		int a, b;
		cin >> a >> b;
		tree[a].push_back(b);
		tree[b].push_back(a);
	}
	bfs(1, -1, 0);
	bfs(max_idx, -1, 0);
	cout << max_length << endl;
	return 0;
}

  

时间: 2024-10-13 10:56:58

[hiho 11]树的直径的相关文章

BDFZOI 树的直径

提交次数:2 涉及知识:基础图论/BFS 描述 一棵树T的"直径"定义为结点两两间距离的最大值.给定带权树T,求T的直径长度. 输入 第一行包含2个整数N.M,表示图中共有N个结点和M条无向边.(N <= 5000,M<n)接下来M行,每行包含3个整数{u,v,w},表示有一条无向边连接结点u.v*输入保证是无环图输出一个整数,代表直径长度 样例输入 4 31 2 12 3 22 4 3 样例输出 5 代码: 1 #include<iostream> 2 #in

hdu 4607(树的直径)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4607 题解:给定一棵树,从树中的任意选一个顶点出发,遍历K个点的最短距离是多少?(每条边的长度为1) 算法分析: 首先如果k小于等于直径长度,那么答案为k−1;如果k大于直径长度,设直径长度为r,那么答案为r−1+(k−r)*2;树的直径:树上的最长简单路径; 代码: 1 #include <cstdio> 2 #include <cmath> 3 #include <cstri

BZOJ 2282 &amp; 树的直径

SDOI2011的Dayx第2题 题意: 在树中找到一条权值和不超过S的链(为什么是链呢,因为题目中提到“使得路径的两端都是城市”,如果不是链那不就不止两端了吗——怎么这么机智的感觉...),使得不在链上的点与这条链的距离最大值最小. SOL: 最大值最小!这不是二分的节奏么?然而hzw学长说二分更直观我却一点都没有体会到... 这道题的关键是猜想(貌似还挺好想)并证明(貌似一直都是可有可无的东西,不过还挺好证的),路径一定在直径上,那么我们先两遍*FS找到直径,用一个队列维护链上的路径,以及预

树的直径

*总结的别人博客 树的直径(Diameter)是指树上的最长简单路.直径的求法:两遍BFS (or DFS)任选一点u为起点,对树进行BFS遍历,找出离u最远的点v以v为起点,再进行BFS遍历,找出离v最远的点w.则v到w的路径长度即为树的直径*简单证明于是原问题可以在O(E)时间内求出 关键在于证明第一次遍历的正确性,也就是对于任意点u,距离它最远的点v一定是最长路的一端.如果u在最长路上,那么v一定是最长路的一端.可以用反证法:假设v不是最长路的一端,则存在另一点v’使得(u→v’)是最长路

【HDOJ2196】Computer(树的直径,树形DP)

题意:给定一棵N个点树,询问这个树里面每个点到树上其他点的最大距离. n<=10000 思路:设f[u,1],f[u,2]为以U为根向下的最长与次长,g[u,1],g[u,2]为从哪个儿子转移来 第一次dfs用V更新U,第二次dfs用U更新V,因为有V向U往上走的情况,这样做就可以处理了 可以发现这些数值中取最大值就是树的直径了 1 var f,g:array[1..21000,1..2]of longint; 2 head,vet,next,len:array[1..21000]of long

CodeForces 14D 树的直径 Two Paths

给出一棵树,找出两条不相交即没有公共点的路径,使得两个路径的长度的乘积最大. 思路:枚举树中的边,将该边去掉,分成两棵树,分别求出这两棵树的直径,乘起来维护一个最大值即可. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 7 const int maxn = 200 + 10; 8 9

UVA 11695 Flight Planning 修改一条边使得树的直径最短

题目链接:点击打开链接 题意: 给定n(n<=2500) 节点的一棵树 删除一条边再加入一条边使得树的直径最短. 思路:首先枚举删除的那条边, 然后计算出删除后的2棵子树各自的重心 则新建的边一定是重心的连线. 而新的直径要么是在某个子树中,要么是两个子树间. #include <cstdio> #include <algorithm> #include <string.h> #include <queue> #include <cstring&

poj:1985:Cow Marathon(求树的直径)

Cow Marathon Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 5496   Accepted: 2685 Case Time Limit: 1000MS Description After hearing about the epidemic of obesity in the USA, Farmer John wants his cows to get more exercise, so he has com

codeforces GYM 100114 J. Computer Network tarjan 树的直径 缩点

J. Computer Network Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Description The computer network of “Plunder & Flee Inc.” consists of n servers and m two-way communication links. Two servers can communicate either thr