noip第21课作业

1. 遍历二叉树

【问题描述】

以先序的方式建立一棵二叉树,空结点用‘#’号表示,例如:abd###ce##f##,将建立一棵如下的二叉树:

输出其中序序列和后序序列,其中总结点个数不超过100。

输入:仅一行,输入一串字符串,该字符串必须能构成一棵二叉树;

输出:两行,第一行为中序序列,第二行为后序序列。

【样例输入】

 abd###ce##f##

【样例输出】

dbaecf

dbefca

#include<iostream>
using namespace std;
struct node{
    char value;
    int left,right;//左右孩子子树
}data[100]; 
char ch;
int cnt,root;
//建立一棵二叉树   abd###ce##f##
int buildTree(int bt){
    cin >> ch;
    if(ch == '#'){
        bt = 0;
    }
    else{
        bt = ++cnt;
        data[bt].value = ch;
        data[bt].left = data[bt].right = 0;
        data[bt].left = buildTree(bt);
        data[bt].right = buildTree(bt);
    }
    return bt;
} 
//中序序列
void MidTree(int bt){
    if(bt){
        MidTree(data[bt].left);
        cout << data[bt].value;
        MidTree(data[bt].right);
    }
} 
//后序序列
void LastTree(int bt){
    if(bt){
        LastTree(data[bt].left);
        LastTree(data[bt].right);
        cout << data[bt].value;
    }
} 
int main()
{
    root = 0;
    cnt = 0;
    root = buildTree(0);    
    MidTree(root);
    cout << endl;
    LastTree(root); 
    return 0;
}

2. 计算二叉树的结点个数

【问题描述】

以先序的方式建立一棵二叉树,空结点用‘#’号表示,例如:abd###ce##f##,将建立一棵如下的二叉树:

输出其总结点的个数,其中总结点个数不超过100。

输入:仅一行,输入一串字符串,该字符串必须能构成一棵二叉树;

输出:仅一行,为该二叉树的结点个数。

【样例输入】

 abd###ce##f##

【样例输出】

 6

#include<iostream>
using namespace std;
struct node{
    char value;
    int left,right;//左右孩子子树
}data[100]; 
char ch;
int cnt,root;
//建立一棵二叉树   abd###ce##f##
int buildTree(int bt){
    cin >> ch;
    if(ch == '#'){
        bt = 0;
    }
    else{
        bt = ++cnt;
        data[bt].value = ch;
        data[bt].left = data[bt].right = 0;
        data[bt].left = buildTree(bt);
        data[bt].right = buildTree(bt);
    }
    return bt;
} 
//计算结点数
int Node(int bt){
    if(bt){
        if(data[bt].left == 0 && data[bt].right == 0)  return 1;
        else return Node(data[bt].left)+Node(data[bt].right) + 1;
    }
    else return 0;
} 
int main()
{
    root = 0;
    cnt = 0;
    root = buildTree(0);
    cout << Node(root) << endl;
    return 0;
}

3. 计算二叉树的叶子结点个数

【问题描述】

以先序的方式建立一棵二叉树,空结点用‘#’号表示,例如:abd###ce##f##,将建立一棵如下的二叉树:

输出其叶子结点的个数,其中总结点个数不超过100。

输入:仅一行,输入一串字符串,该字符串必须能构成一棵二叉树;

输出:仅一行,为该二叉树的叶子结点的个数。

【样例输入】

 abd###ce##f##

【样例输出】

 3

#include<iostream>
using namespace std;
struct node{
    char value;
    int left,right;//左右孩子子树
}data[100]; 
char ch;
int cnt,root;
//建立一棵二叉树   abd###ce##f##
int buildTree(int bt){
    cin >> ch;
    if(ch == '#'){
        bt = 0;
    }
    else{
        bt = ++cnt;
        data[bt].value = ch;
        data[bt].left = data[bt].right = 0;
        data[bt].left = buildTree(bt);
        data[bt].right = buildTree(bt);
    }
    return bt;
} 
//计算叶子数
int Leaf(int bt){
    if(bt){
        if(data[bt].left == 0 && data[bt].right == 0){
            return 1;
        }
        else return Leaf(data[bt].left)+Leaf(data[bt].right);
    }
    else return 0;
}
int main()
{
    root = 0;
    cnt = 0;
    root = buildTree(0);
    cout << Leaf(root) << endl;
    return 0;
}

4. 解密犯罪团伙

【问题描述】

快过年了,犯罪分子们也开始为年终奖“奋斗”了,小明的家乡出现了多次抢劫事件。由于强盗人数过于庞大,作案频繁,警方想查清楚到底有几个犯罪团伙实在是太不容易了,不过呢,经过很多天的努力,警察叔叔还是搜集到了一些线索,需要聪明的我们编写程序帮助警察叔叔分析一下有多少个独立的犯罪团伙?

输入格式:输入第一行为n,m,n表示强盗的人数,m表示警方搜集到的m条线索。接下来m行每一行有两个数a,b,表示强盗a和强盗b是通过。

数据范围说明:(1≤n≤20000),(1≤m≤1000000),1≤a,b≤n。

【输入样例】              

10 9

1 2

3 4

5 2

4 6

2 6

8 7

9 7

1 6

2 4

【输出样例】

3

#include<iostream>
using namespace std;
int f[1000] = {},n,m,k,sum = 0;
//数组初始化,数组里存的是自己的下标 
void init(){
    for(int i = 1; i <= n; i++){
        f[i] = i;
    } 
}
//查找过程
int getf(int v){
    if(f[v] == v){
        return v;
    }
    else{
        f[v] = getf(f[v]); 
        return f[v];
    }
}
//合并的过程
void merge(int x, int y){
    int t1,t2;
    t1 = getf(x);
    t2 = getf(y);
    if(t1 != t2){
        f[t2] = t1;
    }
} 
int main()
{
    int i,x,y;
    cin >> n >> m;
    init();
    for(i = 1; i <= m; i++){
        cin >> x >> y;
        merge(x,y);
    }
    for(i = 1; i <= n; i++){
        if(f[i] == i) sum++;
    }
    cout << sum << endl;
    return 0;
}

1. 小球下落

【问题描述】

  许多的小球一个一个的从一棵满二叉树上掉下来组成FBT(Full Binary Tree,满二叉树),每一时间,一个正在下降的球第一个访问的是非叶子节点。然后继续下降时,或者走右子树,或者走左子树,直到访问到叶子节点。决定球运动方向的是每个节点的布尔值。最初,所有的节点都是false,当访问到一个节点时,如果这个节点时false,则这个球把它变成true,然后从左子树走,继续他的旅程。如果节点时true,则球也会改变它为false,而接下来从右子树走。满二叉树的标记方法如下图:

因为所有的节点最初为false,所以第一个球将会访问节点1,节点2和节点4,转变节点的布尔值后在节点8停止。第二个球将会访问节点1,3,6,在节点12停止。明显地,第三个球在它停止之前,会访问节点1,2,5,在节点10停止。现在你的任务是,给定FBT的深度D,和I,表示第I个小球下落,你可以假定I不超过给定的FBT的叶子树,写一个程序求小球停止时的叶子序号。

输入:仅一行,包含两个用空格隔开的整数D和I(2≤D≤20,I≤I≤524288)。

输出:对应输出第1个小球下落停止时的叶子序号。

【样例输入】4 2

【样例输出】12

#include<iostream>
using namespace std;
bool tree[1024*1024];
int main()
{
    int d,k,i,j,p;
    cin >> d >> k;
    for(i = 1; i <= k; i++){  //枚举每一个球的下落情况
        p = 1;
        for(j = 1; j < d; j++){   
            if(tree[p] == false){  //结点的值为0 
                tree[p] = true;
                p *= 2;            //向左走 
            }
            else{                  //结点的值为 1 
                tree[p] = false;  
                p = p*2+1;        //向右走 
            }
        }
    }
    cout << p << endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zhplovelnn/p/10384814.html