【树】树的直径和重心

目录

一.树的直径

(1)定义

(2)思路

(3)例题

(4)std(第一小问)

二.树的重心

(1)介绍

(2)求重心

(3)例题

(4)AC


一.树的直径

(1)定义

树的直径是指树中最长的一条路径的长度,这条路径连接树中的两个节点,使得它们之间的距离最远。

(2)思路

(3)例题

P3304 [SDOI2013] 直径 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

(4)std(第一小问)

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
int n;
struct Edge{
	int u,v,w,next;
}edge[maxn<<1];
int head[maxn],cnt;
void add(int u,int v,int w){
	edge[++cnt]=(Edge){u,v,w,head[u]}; head[u]=cnt;
}
int root,lon;
void dfs(int u,int fa,int p){
	if(p>lon){
		root=u;
		lon=p;
	}
	for(int i=head[u];i;i=edge[i].next){
		int v=edge[i].v;
		if(v==fa) continue;
		dfs(v,u,p+edge[i].w);
	}
}
int main(){
	scanf("%d",&n);
	for(int i=1,u,v,w;i<n;i++){
		scanf("%d%d%d",&u,&v,&w);
		add(u,v,w); add(v,u,w);
	}
	dfs(1,0,0);
	lon=0;
	dfs(root,0,0);
	printf("%d",lon);
	return 0;
}

二.树的重心

(1)介绍

树的重心是指树中的一个节点,通过删除该节点后,将树分成多个子树,使得每个子树的节点数都不超过整棵树节点数的一半。换句话说,树的重心是树的一种结构特征,它能够将树尽可能平衡地分割成多个相对均匀的部分。

说人话就是重心在树所有节点中,它的最大子树的节点最小

寻找树的重心通常可以通过以下步骤来实现:

  1. 选择任意一个节点作为树的根节点。
  2. 对树进行深度优先搜索(DFS)或广度优先搜索(BFS),计算每个节点的子树大小(包括自身节点)。
  3. 对于每个节点,计算删除该节点后,各个子树的大小(即除去该节点后,以其邻居节点为根的子树大小)。
  4. 找到一个节点,使得删除该节点后,各个子树的大小都不超过整棵树节点数的一半。这个节点就是树的重心。

(2)求重心

cpp 复制代码
#include<bits/stdc++.h>
#define maxn 10005
using namespace std;
int n;
int size[maxn],f[maxn]; //子树总大小 && 最大子树 
struct Edge{
	int u,v,next;
}edge[maxn<<1];
int head[maxn],cnt;
void add(int u,int v){
	edge[++cnt]=(Edge){u,v,head[u]}; head[u]=cnt;
}
int root,MAX=0x7fffffff;
void dfs(int u,int fa){
	size[u]=1;
	for(int i=head[u];i;i=edge[i].next){
		int v=edge[i].v;
		if(v!=fa){
			dfs(v,u);
			size[u]+=size[v];
			f[u]=max(f[u],size[v]);
		}
	}
	f[u]=max(f[u],n-size[u]);
	if(f[u]<MAX ||f[u]<=MAX && u<root){
		MAX=f[u];
		root=u;
	} 
}

int main(){
	scanf("%d",&n);
	int x,y;
	for(int i=1;i<n;i++){
		scanf("%d%d",&x,&y);
		add(x,y); add(y,x);
	}
	dfs(1,0);
	printf("%d",root);
	return 0;
}

(3)例题

P1395 会议 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

(4)AC

cpp 复制代码
#include<bits/stdc++.h>
#define maxn 50005
using namespace std;
int n;
int size[maxn],f[maxn]; //子树总大小 && 最大子树 
struct Edge{
	int u,v,w,next;
}edge[maxn<<1];
int head[maxn],cnt;
void add(int u,int v,int w){
	edge[++cnt]=(Edge){u,v,w,head[u]}; head[u]=cnt;
}
int root,MAX=0x7fffffff;
void dfs(int u,int fa){
	size[u]=1;
	for(int i=head[u];i;i=edge[i].next){
		int v=edge[i].v;
		if(v!=fa){
			dfs(v,u);
			size[u]+=size[v];
			f[u]=max(f[u],size[v]);
		}
	}
	f[u]=max(f[u],n-size[u]);
	if(f[u]<MAX ||f[u]<=MAX && u<root){
		MAX=f[u];
		root=u;
	} 
}
struct node{
	int u,w;
	bool operator < (const node &x) const{
		return x.w<w;
	}
};
int dis[maxn],vis[maxn];
void Djkstra(){
	for(int i=1;i<=n;i++) dis[i]=0x7fffffff;
	dis[root]=0;
	priority_queue<node> q;
	q.push((node){root,0});
	while(!q.empty()){
		node temp=q.top(); q.pop();
		int u=temp.u;
		if(vis[u]) continue;
		vis[u]=1;
		for(int i=head[u];i;i=edge[i].next){
			int v=edge[i].v,w=edge[i].w;
			if(dis[u]+w<dis[v]){
				dis[v]=dis[u]+w;
				q.push((node){v,dis[v]});
			}
		}
	}
}
int main(){
	scanf("%d",&n);
	int x,y;
	for(int i=1;i<n;i++){
		scanf("%d%d",&x,&y);
		add(x,y,1); add(y,x,1);
	}
	dfs(1,0);
	printf("%d ",root);
	Djkstra();
	long long ans=0;
	for(int i=1;i<=n;i++) ans+=dis[i];
	printf("%lld",ans);
	return 0;
}
相关推荐
KingRumn5 小时前
Linux信号之标准信号与实时信号
linux·算法
源代码•宸8 小时前
Leetcode—620. 有趣的电影&&Q3. 有趣的电影【简单】
数据库·后端·mysql·算法·leetcode·职场和发展
2301_800256118 小时前
地理空间数据库中的CPU 和 I/O 开销
数据库·算法·oracle
一个不知名程序员www9 小时前
算法学习入门---结构体和类(C++)
c++·算法
XFF不秃头11 小时前
力扣刷题笔记-旋转图像
c++·笔记·算法·leetcode
王老师青少年编程11 小时前
csp信奥赛C++标准模板库STL案例应用3
c++·算法·stl·csp·信奥赛·lower_bound·标准模版库
有为少年12 小时前
Welford 算法 | 优雅地计算海量数据的均值与方差
人工智能·深度学习·神经网络·学习·算法·机器学习·均值算法
Ven%12 小时前
从单轮问答到连贯对话:RAG多轮对话技术详解
人工智能·python·深度学习·神经网络·算法
山楂树の12 小时前
爬楼梯(动态规划)
算法·动态规划