学习总结10

# 遍历问题

## 题目描述

我们都很熟悉二叉树的前序、中序、后序遍历,在数据结构中常提出这样的问题:已知一棵二叉树的前序和中序遍历,求它的后序遍历,相应的,已知一棵二叉树的后序遍历和中序遍历序列你也能求出它的前序遍历。然而给定一棵二叉树的前序和后序遍历,你却不能确定其中序遍历序列。

所有这些二叉树都有着相同的前序遍历和后序遍历,但中序遍历却不相同。

## 输入格式

共两行,第一行表示该二叉树的前序遍历结果 s1,第二行表示该二叉树的后序遍历结果 s2。

## 输出格式

输出可能的中序遍历序列的总数,结果不超过 2^63-1。

## 样例 #1

### 样例输入 #1

```
abc                           
cba
```

### 样例输出 #1

```
4
```

解题思路

这个题目,我发现我们通过观察前序和后序的遍历顺序可以确定根的位置,然后前序向后遍历,后序向前遍历如果两个遍历的数据一样就表明两个根之间有两种可能。

代码

#include 
using namespace std;
int main()
{
    string g,j;
    long long x,y,sum=1;
    cin>>g>>j;
    for(x=0;x

# 亲戚

## 题目背景

若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系。

## 题目描述

规定:x 和 y 是亲戚,y 和 z 是亲戚,那么 x 和 z 也是亲戚。如果 x,y 是亲戚,那么 x 的亲戚都是 y 的亲戚,y 的亲戚也都是 x 的亲戚。

## 输入格式

第一行:三个整数 n,m,p,(n,m,p <= 5000),分别表示有 n 个人,m 个亲戚关系,询问 p 对亲戚关系。

以下 m 行:每行两个数 Mi,Mj,1 <= Mi,Mj<= n,表示 Mi 和 Mj 具有亲戚关系。

接下来 p 行:每行两个数 Pi,Pj,询问 Pi 和 Pj 是否具有亲戚关系。

## 输出格式

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
```

解题思路

利用数组来模仿二叉树,然后利用并查集的思想来对数据进行合并,然后对每一对数据进行查找,看看他们的根节点是否相同。

代码

#include 
using namespace std;
int g[10001];
int main()
{
    int x,n,m,b,c,p;
    scanf("%d%d%d",&n,&m,&p);
    for(x=1;x<=n;x++)                    //对数组进行赋初值
        g[x]=x;
    for(x=0;x

# 朋友

## 题目背景

小明在 A 公司工作,小红在 B 公司工作。

## 题目描述

这两个公司的员工有一个特点:一个公司的员工都是同性。

A 公司有 N 名员工,其中有 P 对朋友关系。B 公司有 M 名员工,其中有 Q 对朋友关系。朋友的朋友一定还是朋友。

每对朋友关系用两个整数 Xi,Yi 组成,表示朋友的编号分别为 Xi,Yi。男人的编号是正数,女人的编号是负数。小明的编号是 1,小红的编号是 -1。

大家都知道,小明和小红是朋友,那么,请你写一个程序求出两公司之间,通过小明和小红认识的人最多一共能配成多少对情侣(包括他们自己)。

## 输入格式

输入的第一行,包含 4 个空格隔开的正整数 N,M,P,Q。

之后 P 行,每行两个正整数 Xi,Yi。

之后 Q 行,每行两个负整数 Xi,Yi。

## 输出格式

输出一行一个正整数,表示通过小明和小红认识的人最多一共能配成多少对情侣(包括他们自己)。

## 样例 #1

### 样例输入 #1

```
4 3 4 2
1 1
1 2
2 3
1 3
-1 -2
-3 -3
```

### 样例输出 #1

```
2
```

## 提示

对于 30 % 的数据,N,M <=100,P,Q <= 200;

对于 80 % 的数据,N,M <= 4 * 10^3,P,Q <= 10^4;

对于 100 % 的数据,N,M <= 10^4,P,Q <= 2 * 10^4。

解题思路

这道题把公司分为了全是男人的公司和全是女人的公司,这样我们只要把两个公司分别用两个数组模拟树,然后把每一个和小明和小红有关系的人比较,选出最小的哪一个输出就行了。

代码

#include 
using namespace std;
int g[200010];
int j[200010];
int findm(int x)                     //查找男公司数据的根
{
    if(g[x]==x)
        return x;
    return g[x]=findm(g[x]);
}
int findw(int x)                     //查找女公司数据的根
{
    if(j[x]==x)
        return x;
    return j[x]=findw(j[x]);
}
void jiem(int x,int y)               //链接男公司里的人
{
    x=findm(x);
    y=findm(y);
    if(x!=y)
        g[x]=y;
}
void jiew(int x,int y)               //链接女公司里的人
{
    x=findw(x);
    y=findw(y);
    if(x!=y)
        j[x]=y;
}
int main()
{
    int x,n,m,b,c,p,q;
    int sum=0,sum1=0;
    scanf("%d%d%d%d",&n,&m,&p,&q);
    for(x=1;x<=n;x++)                      //进行数组初始化
        g[x]=x;
    for(x=1;x<=m;x++)
        j[x]=x;

    for(x=0;x

 今日总结

今天学习了查并集和树的基础,写了几道题目,准备明天学习一下简单的二分和动态规划并做一些题目进行练习

你可能感兴趣的:(学习)