今天也是写代码的一天。没什么活可讲的,上代码吧!
P1030 [NOIP2001 普及组] 求先序排列
# [NOIP2001 普及组] 求先序排列
## 题目描述
给出一棵二叉树的中序与后序排列。求出它的先序排列。(约定树结点用不同的大写字母表示,且二叉树的节点个数 $ \le 8$)。
## 输入格式
共两行,均为大写字母组成的字符串,表示一棵二叉树的中序与后序排列。
## 输出格式
共一行一个字符串,表示一棵二叉树的先序。
## 样例 #1
### 样例输入 #1
```
BADC
BDCA
```
### 样例输出 #1
```
ABCD
```
## 提示
**【题目来源】**
这样的题目跟上次做的差不多。唯一要注意的是他的停止条件。在我写的代码中,我的DFS停止条件是如果有一端为空,也就是说搜寻不到什么了,则停止。
代码如下
#include<bits/stdc++.h>
using namespace std;
void dfs(string s1,string s2){
if(s1.length()==0)return;
int c;
c=s2.length();
char root=s2[c-1];
int l=s1.find(root);
string s1_l=s1.substr(0,l),s2_l=s2.substr(0,l);
string s1_r=s1.substr(l+1,c-l-1),s2_r=s2.substr(l,c-l-1);
cout<<root;
dfs(s1_l,s2_l);
dfs(s1_r,s2_r);
}
int main(){
string s1,s2;
cin>>s1>>s2;
dfs(s1,s2);
return 0;
}
P1551 亲戚
# 亲戚
## 题目背景
若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系。
## 题目描述
规定:$x$ 和 $y$ 是亲戚,$y$ 和 $z$ 是亲戚,那么 $x$ 和 $z$ 也是亲戚。如果 $x$,$y$ 是亲戚,那么 $x$ 的亲戚都是 $y$ 的亲戚,$y$ 的亲戚也都是 $x$ 的亲戚。
## 输入格式
第一行:三个整数 $n,m,p$,($n,m,p \le 5000$),分别表示有 $n$ 个人,$m$ 个亲戚关系,询问 $p$ 对亲戚关系。
以下 $m$ 行:每行两个数 $M_i$,$M_j$,$1 \le M_i,~M_j\le n$,表示 $M_i$ 和 $M_j$ 具有亲戚关系。
接下来 $p$ 行:每行两个数 $P_i,P_j$,询问 $P_i$ 和 $P_j$ 是否具有亲戚关系。
## 输出格式
$p$ 行,每行一个 `Yes` 或 `No`。表示第 $i$ 个询问的答案为“具有”或“不具有”亲戚关系。
## 样例 #1
### 样例输入 #1
```
6 5 3
1 2
1 5
3 4
5 2
1 3
1 4
2 3
5 6
```
### 样例输出 #1
```
Yes
Yes
No
```
思路:这是一个典型的并查集问题。我们首先应该将输入的数初始化,即将他的父亲定义为自身。再将他们合,也就是定义他们相互的关系,让他们联系起来。然后再是查询他们的祖先。在查询他们的祖先的过程中, 我们要用到递归,查询直到他们的祖先等于自身时停止。在题目中如果他们是亲戚则输出yes,如果不是则输出no,转化为代码则是,如果他们的祖先相同,则输出yes,如果不同则输出no。
代码
#include<bits/stdc++.h>
using namespace std;
int fa[5005];
void init(int n){
for(int i=1;i<=n;i++){
fa[i]=i;
}
}
int find(int i){
if(i==fa[i])
return i;
else{
fa[i]=find(fa[i]);
return fa[i];
}
}
int n,m,p,x,y;
int main(){
cin>>n>>m>>p;
init(n);
for(int i=0;i<m;i++){
cin>>x>>y;
int fx=find(x),fy=find(y);
if(fx!=fy){
fa[fx]=fy;
}
}
for(int i=0;i<p;i++){
cin>>x>>y;
if(find(x)==find(y)){
cout<<"Yes"<<endl;
}
else{
cout<<"No"<<endl;
}
}
return 0;
}
在并查集这道题中,我学会了如何将数合并,并且利用递归的方式将路程压缩。每天进步一点点,加油!