北邮OJ-267-最小堆-14网研上机B

算法分析:本来打算使用标准的二叉树模板自上而下递归检索是否是最小堆,然而题目给的输入结构竟然给了更好解法的提示:使用双亲表示法自下而上检索——是的没错,就是套用“并查集模板”。
(复杂度nlog(n),还可以继续优化(剪枝),不过优化完复杂度还是这个数量级,反正n很小不会超时,懒得写了)

Problem B. 最小堆
题目描述
给定一棵带权二叉树,请判断它是不是一个最小堆。
一棵二叉树是一个最小堆,当且仅当对于树上任意一个节点,它的权值都小于或等于以它为根的子树中的所有权值。
输入格式
输入数据第一行是一个整数T(1<=T<=100),表示测试数据的组数。
对于每组测试数据:
第一行是一个整数N(1<=N<=100),表示树的节点个数。
接下来一行包含N个正整数,第i个整数valuei(1<=valuei<=1000)表示编号i的点的权值。
接下来N-1行,每行两个整数u和v(1<=u,v<=N, u!=v),表示节点u是节点v的父节点。
测试数据保证给定的一定是一棵二叉树,并且节点1是树的根结点。
输出格式
对于每组测试数据,如果给定的树是一个最小堆则输出Yes,否则输出No。
输入样例
3
1
10
3
10 5 3
1 2
1 3
5
1 2 3 4 5
1 3
1 2
2 4
2 5
输出样例
Yes
No
Yes

/*并查集。
father[]原本记录i结点的双亲结点下标(本质即为树的双亲表示法)
将findRoot方法添加了reduce deep功能后,father[]退化为记录i结点的根节点 

*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#define MAXSIZE 200 
using namespace std;
bool isSmallHeap; 

struct Set{ //UnionFindSet 从0开始 
    int father[MAXSIZE]; 
    int value[MAXSIZE];
    int setSize;
    int initSet(int setSize){
        this->setSize=setSize;
        for (int i=0;i<MAXSIZE;i++){
            father[i]=-1;
        }
    }
    //findRoot方法功能:找到x结点的根 
    int findRoot(int x){
        while (father[x]!=-1){
            if (value[x]<value[father[x]]){
                isSmallHeap=false;
                return -1;//中途return 
            }
            x=father[x];
        }
        return x;
    }
};
int main(){
    int t,n;
    int u,v;
    Set set;
    int value;
    scanf("%d",&t);
    for (int time=0;time<t;time++){
        scanf("%d",&n);
        //initiate
        set.initSet(n);
        isSmallHeap=true;
        //input
        for (int i=0;i<n;i++){
            scanf("%d",&value);
            set.value[i]=value;
        }
        for (int i=0;i<n-1;i++){
            scanf("%d%d",&u,&v);    
            u--;v--;
            set.father[v]=u;
        }
        //search
        for (int i=0;i<n;i++){
            set.findRoot(i);
        }
        //output
        printf("%s\n",isSmallHeap?"Yes":"No");/*bug*/
    }

    return true;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章