目录
编程题——吝啬的国度
题目:
吝啬的国度
时间限制: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(宽(广)度优先搜索)搜索每个节点,把上一个节点保存下来,最后输出。
思路:
- 输入
- 建造树
- 宽(广)度优先搜索
- 输出
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为根。
有的可能隐藏在题目里,比如吝啬的国度,他没有告诉你求父节点,可经过分析,就是求父节点
所以我们做题时要多读题,才能明白这道题要求什么
总结
这次我主要讲了以下内容
- 题目:吝啬的国度(树的存储+树的信息表示+宽(广)度优先搜索)
- 树用链式前向星存储
- 树的信息表示