北郵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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章