图论——树有关知识

这篇具有很好参考价值的文章主要介绍了图论——树有关知识。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

树的遍历顺序有关

前序,中序,后序概念自行百度。

知道几种顺序来确定二叉树形态

首先先明确一点至少要知道两种顺序以上才能确定一个树,因为如果只知道前序或者后序就只能确定根节点,而不能确定根节点的左右子树。但如果知道中序,那就不能确定根节点。

然后如果知道两种顺序的话,必须要知道中序,因为另外一种顺序可以确定根节点,中序来确定根节点的左右子树,然后再根据前序后者后序确定根节点的左右儿子。

具体确定代码实现(前序+中序)

#include<bits/stdc++.h>
using namespace std;
const int N=5e3+50;
string s,t;
int n;
void solve(int l,int r,int ml,int mr)
{
	if(l>r)
		return;
	if(l==r)
	{
		cout<<s[l];
		return;
	}
	int pos;
	for(int i=ml;i<=mr;i++)
		if(t[i]==s[l])
			pos=i;
	solve(l+1,l-ml+pos,ml,pos-1);solve(l-ml+pos+1,r,pos+1,r);
	cout<<s[l];
	return;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin>>s>>t;
	n=s.length();
	s=" "+s;t=" "+t;
	solve(1,n,1,n);
	return 0;
}

结合代码还是很好理解的。

二叉树计数

但还有一种题型,就是已知前序和后序,求有多少种二叉树满足这种遍历顺序。

我们能确定根节点,但是不能确定根节点有一个儿子还是两个儿子。如果一个点有一个儿子,那么就有两种情况,儿子朝左朝右都可以。比如看前序遍历的第二个数,再在后序中找到,如果在后序的下一个位置为根,那么证明根节点只有一个儿子。否则就有两个儿子。

具体代码实现如下。

#include<bits/stdc++.h>
using namespace std;
const int N=5050;
long long ans;
int n,m;
char a[N],b[N];
int main(){
	scanf("%s %s",a,b);
	n=strlen(a);
	for(int i=0;i<n-1;i++)
		for(int j=1;j<n;j++)
			if(a[i]==b[j]&&a[i+1]==b[j-1])ans++;
	printf("%lld\n",(1ll<<ans));
	return 0;
}

多叉树转二叉树

记住口诀 “左儿子,右兄弟”

意义:为什么要把多叉树转为二叉树?因为普遍情况下二叉树性质比多叉树的性质好。

C o d e Code Code

#include<bits/stdc++.h>
using namespace std;
const int N=150;
map<char,char> son,L,R;
map<char,bool> mp,F,xx;
bool hav[N];
char root;int n;
void pre(char u)
{
	cout<<u;
	if(hav[u])pre(L[u]);
	if(mp[u])pre(R[u]);
	return;
}
void mid(char u)
{
	if(hav[u])mid(L[u]);
	cout<<u;
	if(mp[u])mid(R[u]);
	return;
}
void su(char u)
{
	if(hav[u])su(L[u]);
	if(mp[u])su(R[u]);
	cout<<u;
	return;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		char u;cin>>u;xx[u]=true;
		char x;
		while(1)
		{
			cin>>x;
			if(x=='0')break;
			F[x]=true;
			if(!hav[u])L[u]=x;
			else R[son[u]]=x,mp[son[u]]=true;
			son[u]=x;hav[u]=true;
		}
	}
	for(char i='A';i<='Z';i++)
	{
		if(xx[i]&&!F[i])
		 	root=i;
	}
	pre(root);cout<<endl;mid(root);cout<<endl;su(root);
	return 0;
}

树上差分

通常用来求两点之间的距离与经过的点数。

求两点间的距离:
d ( u , v ) = d e p ( u ) + d e p ( v ) − 2 × d e p ( L C A ( u , v ) ) d(u,v)=dep(u)+dep(v)-2\times dep(LCA(u,v)) d(u,v)=dep(u)+dep(v)2×dep(LCA(u,v))

树上贪心

树的重心

定义&性质&证明

定义: 以它为根的所有子树中最大的子树大小最小。则称这个点为树的重心。

性质 1 1 1:一个点是重心,当且仅当以该点为根的最大子树的大小不超过整棵树的大小一半(向下取整,及 $\left \lfloor \frac{n}{2} \right \rfloor $)

证明:
M S S ( u ) MSS(u) MSS(u) 表示节点 u u u 的最大子树大小。 s i z e u ( v ) size_u(v) sizeu(v) 表示以 u u u 为根时,包含节点 v v v 的子树大小。
先证明其充分性:
如果 u u u 为重心,则与 u u u 直接相连的节点 v v v 的大小 s i z e u ( v ) ≤ ⌊ n 2 ⌋ size_u(v) \le \left \lfloor \frac{n}{2} \right \rfloor sizeu(v)2n。考虑反证法,假设节点 u u u 为重心,而存在一个 u u u 的子树使得 $size_u(v) > \left \lfloor \frac{n}{2} \right \rfloor $,则 s i z e v ( u ) = n − s i z e u ( v ) < ⌊ n 2 ⌋ < s i z e u ( v ) = M S S ( u ) size_v(u) = n - size_u(v) < \left \lfloor \frac{n}{2} \right \rfloor < size_u(v) = MSS(u) sizev(u)=nsizeu(v)<2n<sizeu(v)=MSS(u)。对于 w ≠ u w \ne u w=u 又有 s i z e v ( w ) < s i z e u ( v ) = M S S ( u ) size_v(w) < size_u(v) = MSS(u) sizev(w)<sizeu(v)=MSS(u) (因为 w w w 如果是在以 节点 v v v 为根,节点 u u u 为子树中, s i z e v ( u ) < ⌊ n 2 ⌋ < s i z e u ( v ) = M S S ( u ) size_v(u) < \left \lfloor \frac{n}{2} \right \rfloor < size_u(v) = MSS(u) sizev(u)<2n<sizeu(v)=MSS(u),而有如果 w w w v v v 的其他子树中的话,那么 s i z e v ( w ) size_v(w) sizev(w) < s i z e u ( w ) = s i z e u ( v ) = M S S ( u ) size_u(w) = size_u(v) = MSS(u) sizeu(w)=sizeu(v)=MSS(u)),所以 M S S ( v ) < M S S ( u ) MSS(v) < MSS(u) MSS(v)<MSS(u),与重心定义矛盾,所以 u u u 不是重心,得证。
再证明其必要性:
如果一个节点 u u u M S S ( u ) ≤ ⌊ n 2 ⌋ MSS(u) \le \left \lfloor \frac{n}{2} \right \rfloor MSS(u)2n,则 u u u 为重心。 s i z e v ( u ) = n − s i z e u ( v ) ≥ ⌊ n 2 ⌋ ≥ M S S ( u ) size_v(u) = n -size_u(v) \ge \left \lfloor \frac{n}{2} \right \rfloor \ge MSS(u) sizev(u)=nsizeu(v)2nMSS(u)。即 M S S ( v ) ≥ M S S ( u ) MSS(v) \ge MSS(u) MSS(v)MSS(u)。对于与 u u u 不相邻的节点 w w w,都有 s i z e w ( v ) > M S S ( u ) size_w(v) > MSS(u) sizew(v)>MSS(u)。故得证。

性质 2 2 2:树至多有两个重心。如果树有两个重心,那么它们相邻。此时树一定有偶数个节点,且可以被划分为两个大小相等的分支,每个分支各自包含一个重心。

注: 一个偶数节点的树可以有两个重心,也可以只有一个重心,而一个奇数节点的树只可能有一个重心,不可能有两个重心。

证明:
根据上一个证明必要性时, s i z e v ( u ) = n − s i z e u ( v ) ≥ ⌊ n 2 ⌋ ≥ M S S ( u ) size_v(u) = n -size_u(v) \ge \left \lfloor \frac{n}{2} \right \rfloor \ge MSS(u) sizev(u)=nsizeu(v)2nMSS(u) 得到,当 n n n 为偶数时且 s i z e v ( u ) = n 2 = s i z e u ( v ) = M S S ( u ) size_v(u) = \frac{n}{2} = size_u(v) = MSS(u) sizev(u)=2n=sizeu(v)=MSS(u)。故得证。

性质 3 3 3:树中所有点到某个点的距离和中,到重心的距离和是最小的;如果有两个重心,那么到它们的距离和一样。反过来,距离和最小的点一定是重心。

证明:
假设所有点到节点 u u u 的距离最小,且有一个与节点 u u u 相邻的节点 v v v 使得 s i z e u ( v ) > n 2 size_u(v) > \frac{n}{2} sizeu(v)>2n,那么根据调整法所有点到节点 v v v 的距离为 d i s ( u ) − s i z e u ( v ) + ( n − s i z e u ( v ) ) = d i s ( u ) + n − 2 × s i z e u ( v ) dis(u) - size_u(v) + (n - size_u(v)) = dis(u) + n - 2\times size_u(v) dis(u)sizeu(v)+(nsizeu(v))=dis(u)+n2×sizeu(v)。因为 s i z e u ( v ) > n 2 size_u(v) > \frac{n}{2} sizeu(v)>2n,所以 2 × s i z e u ( v ) > n 2\times size_u(v) > n 2×sizeu(v)>n,所以 n − 2 × s i z e u ( v ) < 0 n - 2\times size_u(v) < 0 n2×sizeu(v)<0,即 d i s ( u ) > d i s ( v ) dis(u) > dis(v) dis(u)>dis(v),此时与所有点到节点 u u u 的距离最小矛盾,所以只要一个节点的 u u u M S S ( u ) > n 2 MSS(u) > \frac{n}{2} MSS(u)>2n,那 d i s ( u ) dis(u) dis(u) 一定不是最小值。而如果 M S S ( u ) ≤ n 2 MSS(u) \le \frac{n}{2} MSS(u)2n,那么与 u u u 直接相邻的节点 v v v s i z e u ( v ) ≤ n 2 size_u(v) \le \frac{n}{2} sizeu(v)2n。即不管往哪里调整,都会使 d i s dis dis 值增加。所以再结合根据性质 1 1 1,即可证毕。

性质 4 4 4:往树上增加或减少一个叶子,如果原节点数是奇数,那么重心可能增加一个,原重心仍是重心;如果原节点数是偶数,重心可能减少一个,另一个重心仍是重心。

性质 5 5 5:把两棵树通过一条边相连得到一棵新的树,则新的重心在较大的一棵树一侧的连接点与原重心之间的简单路径上。如果两棵树大小一样,则重心就是两个连接点。

如何求重心

方法一(不能求出最大子树的大小):统计节点 u u u 的子树的大小和除了 u u u 子树的剩余部分的大小看是否都小于 n 2 \frac{n}{2} 2n,如果都小于,那么根据性质1这个节点就是重心,否则不是。

方法二:根据重心的定义,是得最大的子树最小的节点即为重心,所以另 r e s = m a x s i z e u ( v ) , n − s i z e u res=max{size_u(v),n-size_u} res=maxsizeu(v),nsizeu。最小的几个 r e s res res 即为重心,且 r e s res res 表示最大子树最小的值。

代码如下:(采用方法二)文章来源地址https://www.toymoban.com/news/detail-845224.html

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+50;
int head[N],cnt,n,sz[N],ans=1e9;
vector<int> G;
struct edge{
	int to,nxt;
}e[N*2];
void add(int u,int v)
{
	e[++cnt].to=v;
	e[cnt].nxt=head[u];
	head[u]=cnt;
	return;
}
void dfs(int u,int fa)
{
	sz[u]=1;int res=0;
	for(int i=head[u];i;i=e[i].nxt)
	{
		int v=e[i].to;
		if(v==fa)
			continue;
		dfs(v,u);
		res=max(res,sz[v]);
		sz[u]+=sz[v];
	}
	res=max(res,n-sz[u]);
	if(res<ans)
	{
		ans=res;
		G.clear();
		G.push_back(u);
	}
	else if(res==ans)
		G.push_back(u);
	return;
}
int main()
{
	scanf("%d",&n);
	for(int i=1,u,v;i<=n-1;i++)
	{
		scanf("%d %d",&u,&v);
		add(u,v);add(v,u);
	}
	dfs(0,0);
	printf("%d %d\n",ans,(int)G.size());
	for(int i=0;i<(int)G.size();i++)
		printf("%d ",G[i]);
	return 0;
}

到了这里,关于图论——树有关知识的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 微软有关AD域知识,创建AD域,新用户加入域步骤,MDE部署

    AD是Active Directory的缩写,即Windows服务器的活动目录,在目录中可以收录公司的电脑账号,用户账号,组等等以提供更好的安全性和更便捷的管理能力。 域是组织单元,也是来划分安全界限的。当你的公司成长到很大的时候,用一个域来管理各个城市的分公司会造成很多困难

    2024年02月08日
    浏览(34)
  • 【Spring】Spring框架介绍,功能模块,容器知识和有关Spring的生态圈的详细讲解

    作者简介: 辭七七,目前大一,正在学习C/C++,Java,Python等 作者主页: 七七的个人主页 文章收录专栏: 七七的闲谈 欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖 Spring框架是一个开放源代码的J2EE应用程序框架 ,由Rod Johnson发起,是针对bean的生命周期进行管理的轻量级容器(

    2024年02月08日
    浏览(52)
  • java与es8实战之三:Java API Client有关的知识点串讲

    这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇是《java与es8实战》系列的第三篇,将一些重要的知识点在这里梳理清楚,为后面的实践奠定基础 一共有七个与Java API Client有关的重要知识点 关于namespace:每个feature都有自己的package 命名规则:

    2024年02月11日
    浏览(44)
  • 竞赛知识点5【图论】

    图论起源于著名的哥尼斯堡七桥问题——从这四块陆地中任何一块开始,通过每一座桥正好 一次,再回到起点。欧拉在 1736 年解决了这个问题,欧拉证明了这个问题没有解,并且推广 了这个问题,给出了对于一个给定的图可以某种方式走遍的判定法则。这就是后来的欧拉路

    2024年02月09日
    浏览(54)
  • 图论的基本知识

    1.数据结构 图论是数学的一个分支,研究图(Graph)的结构、性质以及它们之间的关系。图是由节点(或顶点)和边组成的一种数据结构,用于表示对象之间的关系。以下是一些图论的基本概念: 图(Graph): 图由节点(顶点)和连接节点的边组成。图可以分为有向图和无向

    2024年02月04日
    浏览(53)
  • 简单图论的知识

    Floyd算法是一种求解多源最短路问题的算法。 在floyd中,图一般用邻接矩阵存储,边权可正可负,利用动态规划思想,逐步求解出任意两点之间的最短距离。 我们需要准备一个数组d[N][N][N],初始化无穷。 d[k][i][j]表示路径(除去起点和终点)中编号最大的点编号=k的情况下,点

    2024年04月13日
    浏览(62)
  • 图论|知识图谱——详解自下而上构建知识图谱全过程

    导读:知识图谱的构建技术主要有自顶向下和自底向上两种。其中自顶向下构建是指借助百科类网站等结构化数据源,从高质量数据中提取本体和模式信息,加入到知识库里。而自底向上构建,则是借助一定的技术手段,从公开采集的数据中提取出资源模式,选择其中置信度

    2024年02月04日
    浏览(42)
  • 图论基础知识 并查集/例题

    学习记录自代码随想录 并查集常用来解决连通性问题。 判断两个元素是否在同一个集合里的时候,要想到用并查集。 并查集主要有两个功能: 1.将两个元素添加到一个集合中; 2.判断两个元素在不在同一个集合。 例题:20240410 Huawei机考

    2024年04月25日
    浏览(35)
  • 图论期末复习知识点 卓新建

    图的定义、关联、相邻、重边、环、孤立点、简单图 同 顶点的度d(v), deg(v)、出度、入度、最大度D、最小度d、奇点、偶点、邻域、悬挂点、 悬挂边 独立集 偶图/二部图/二分图、多部图、完全偶图、完全图、正则图 度序列 、图序列(简单图的度序列) 握手定理 子图、极大子

    2024年02月03日
    浏览(48)
  • 图论专栏一《图的基础知识》

    图论(Graph Theory)是数学的一个分支 。它以图为研究对象。图论中的图是由若干给定的点及连接两点的线所构成的图形,这种图形通常用来描述某些实体之间的某种特定关系,用点代表实体,用连接两点的线表示两个实体间具有的某种关系。 相比矩阵、张量、序列等结构,

    2024年02月03日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包