吝啬的国度——树的存储和信息表示

目录

 编程题——吝啬的国度

 题目吝啬的国度

解题思路

AC代码

知识点—— 树的存储和信息表示

树的存储方式

树的存储代码

树的信息表示

总结


 编程题——吝啬的国度

 题目:

      吝啬的国度

时间限制:1秒        内存限制:128M

题目描述

在一个吝啬的国度里有N个城市,这N个城市间只有N-1条路把这个N个城市连接起来。现在,Tom在第S号城市,他有张该国地图,他想知道如果自己要去参观第T号城市,必须经过的前一个城市是几号城市(假设你不走重复的路)。

输入描述

第一行输入一个正整数N(1<=N<=100000)和一个正整数S(1<=S<=100000),N表示城市的总个数,S表示参观者所在城市的编号,随后的N-1行,每行有两个正整数a,b(1<=a,b<=N),表示第a号城市和第b号城市之间有一条路连通。

输出描述

每组测试数据输N个正整数,其中,第i个数表示从S走到i号城市,必须要经过的上一个城市的编号。(其中i=S时,请输出-1)

样例

输入

10 1
1  9
1  8
8  10
10 3
8  6
1  2
10 4
9  5
3  7

输出

-1 1 10 10 9 8 3 1 1 8

解题思路

从题目描述中得知输入的是一个有N节点,N-1条边,无环的无向图,也就是一棵树。

这道题要求的是到某个城市需要经过的上一个城市,对于树来说就是这个节点的父节点。

但输入数据并没有说明谁是父节点,所以我们只能使用bfs(宽(广)度优先搜索)搜索每个节点,把上一个节点保存下来,最后输出。

思路:

  1. 输入
  2. 建造树
  3. 宽(广)度优先搜索
  4. 输出

AC代码

这是我的完整代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int head[100002];
int ne[200002];
int e[200002];
int ans[100002];
int idx=0,n,s;
void bfs(int x){
	queue<int> q;
	q.push(x);
	ans[x]=-1;
	while(!q.empty()){
		int t=q.front();
		q.pop();
		for(int i=head[t];i!=-1;i=ne[i]){
			if(ans[e[i]]==0){
				ans[e[i]]=t;
				q.push(e[i]);
			}
		}
	}
}
void add(int a,int b){
	e[++idx]=b;
	ne[idx]=head[a];
	head[a]=idx;
}
int main(){
	memset(head,-1,sizeof head);
	cin>>n>>s;
	for(int i=1;i<n;i++){
		int x,y;
		cin>>x>>y;
		add(x,y);
		add(y,x);
	}
	bfs(s);
	for(int i=1;i<=n;i++){
		cout<<ans[i]<<" ";
	}
	return 0;
}

知识点—— 树的存储和信息表示

树的存储方式

二叉树可以用“父亲存储法”和“儿子存储法”,那树要用什么存储方法呢?

树其实可以理解为特殊的图,所以我们就可以用图的存储方法——链式前向星表示法。

下面我们来看输入节点数为n的树的代码及解析。

树的存储代码

​
​
​
#include<iostream>
#include<cstring>
using namespace std;
int head[100002];//存边的编号
int ne[200002];//存邻接边编号
int e[200002];//存连接到的节点
int idx=0,n;//idx:边的编号
//add():新建边的函数
void add(int a,int b){
	e[++idx]=b;//e数组存入终点节点编号
	ne[idx]=head[a];//ne数组存入邻接边编号
	head[a]=idx;//head数组存入编号
}
int main(){
	memset(head,-1,sizeof head);
//head数组注意不要忘了初始化为-1,因为如果边的编号从0开始,编号为0的边就会被当成空
	cin>>n;
	for(int i=1;i<n;i++){
		int x,y;
		cin>>x>>y;
		add(x,y);
		add(y,x);
	}
	for(int i=1;i<=n;i++){
		cout<<ans[i]<<" ";
	}
	return 0;
}

​

​

​

树的信息表示

树的信息表示就是让你根据题目要求输出树的相关信息。

有的可能直接告诉你

比如这几道题:

树的权值深度

求树的各个节点的权值有一种方法是自上而下统计信息。起初,我们已知根节点s的的权值深度为0。若某个节点x的权值深度为d[x],x与它的某个子节点y之间的边的权值为z(1<=z<=10000)则它的子节点y的权值深度d[y]=d[x]+z,现在给你一棵树,让你输出每个节点的权值深度。

树的深度

求树的各个节点的深度可以自上而下统计信息。起初,我们已知根节点的的深度为0.若节点x的深度为d[x],则它的子节点y的深度为d[y]=d[x]+1,现在给你一棵树,让你输出每个节点的深度。

儿子个数统计1

求树中每个点的儿子个数,其中节点1为根。

儿子个数统计2

求树中每个点的儿子个数,假设节点1为根。

有的可能隐藏在题目里,比如吝啬的国度,他没有告诉你求父节点,可经过分析,就是求父节点

所以我们做题时要多读题,才能明白这道题要求什么

总结

这次我主要讲了以下内容

  1. 题目:吝啬的国度(树的存储+树的信息表示+宽(广)度优先搜索)
  2. 树用链式前向星存储
  3. 树的信息表示
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值