&& 해시 트리 동형 튜토리얼 [BJOI2015] 트리

주제 링크

뿌리 트리 해시

의 해시 트리의 이산 수학 설명을 여기에 . 우리는 볼 수 있습니다.

구조와 뿌리 나무가 있는지 여부를 결정, 그것은 뿌리 트리 코딩 간주 될 수 있습니다. 서로 다른 서브 트리의 순서를 무시하고, 부호화 처리를, 또, 트리 형태 적 특징을 보유 할 필요가있다. 이 방법의 첫 번째보기 :

당신은 트리 코딩이 문자열인지 확인하실 수 있습니다 \ (T \) .

포인트를 들어 \ (U \) 먼저 찾아 \을 (U \) 모든 \ (son_u \) 인코딩 \ (son_u F_ {} \) , 다음이가주는 큰 작은에서 사전 식 순서로 코딩 \을 (G_ { . 1 \ K} cdots \) . 이어서 \ (f_u = "0"+ \ SUM \는 \ G_i +. "1"로 제한) .

그래서 \ (T \) 코딩의 루트 노드로 인코딩됩니다.

당신은 길을 디코딩하여이 알고리즘의 정확성을 확인할 수 있습니다.

이 코드는 단지 숫자입니다 해시 트리 간주되지 않습니다. 이 코드는 정확성을 보장합니다. 사실, 우리가 일반적으로 사용하는 경우와 (공간이 너무 많은 시간이다)이 허용 할 수 없습니다. 우리는 일반적으로 작업을 모듈로 및 방법 값을 사용합니다. 사실, 작업의 값은 가능한 한 많이 충족 保留树形态的特征,同时忽略子树顺序的不同. 또한, XOR, 정렬 등이 가능합니다.

방법 해시 트리, 매우 큰 OIwiki에 세 가지 일반적인 방법이있다 .

루팅 해제 나무 해시

일반적으로 루트를 선택하여 루팅 해제 나무함으로써 루팅 해제 나무를 인코딩 달성, 뿌리 트리로 설정합니다. 선택된 번호의 일반적인 루트 센터. 작은 센터 루트를 코딩 선택에 두 센터가있는 경우. 진리를 위해 거의 같은 해시이다.

데이터 범위가 매우 작기 때문에이 질문에 대해 직접적인 폭력 코딩, 그래서지도는 다시 선고 할 수있다.

#include <bits/stdc++.h>
using namespace std;

const int Maxn = 60;
struct edge {
    int To, Next;
    edge() {}
    edge( int _To, int _Next ) : To( _To ), Next( _Next ) {}
};
int Start[ Maxn ], Used;
edge Edge[ Maxn << 1 ];
inline void AddEdge( int x, int y ) {
    Edge[ ++Used ] = edge( y, Start[ x ] );
    Start[ x ] = Used;
    return;
}

map< string, int > Map;
string A[ Maxn ], B[ Maxn ], S;
int n, m, T[ Maxn ];
int Cnt, Rt[ Maxn ];

int Dfs1( int u, int Fa ) {
    int Size = 1, IsR = 1;
    for( int t = Start[ u ]; t; t = Edge[ t ].Next ) {
        int v = Edge[ t ].To;
        if( v == Fa ) continue;
        int T = Dfs1( v, u );
        if( T > n / 2 ) IsR = 0;
        Size += T;
    }
    if( n - Size > n / 2 ) IsR = 0;
    if( IsR ) Rt[ ++Cnt ] = u;
    return Size;
}

void Cal( int u, int Fa ) {
    for( int t = Start[ u ]; t; t = Edge[ t ].Next ) {
        int v = Edge[ t ].To;
        if( v == Fa ) continue;
        Cal( v, u );
    }
    A[ u ] = "0";
    int Cnt = 0;
    for( int t = Start[ u ]; t; t = Edge[ t ].Next ) {
        int v = Edge[ t ].To;
        if( v == Fa ) continue;
        B[ ++Cnt ] = A[ v ];
    }
    sort( B + 1, B + Cnt + 1 );
    for( int i = 1; i <= Cnt; ++i )
        A[ u ] = A[ u ] + B[ i ];
    A[ u ] = A[ u ] + "1";
    return;
}

int main() {
    scanf( "%d", &m );
    for( int i = 1; i <= m; ++i ) {
        memset( Start, 0, sizeof( Start ) );
        Used = 0;
        scanf( "%d", &n );
        for( int j = 1; j <= n; ++j ) {
            int x;
            scanf( "%d", &x );
            if( x == 0 ) continue;
            AddEdge( x, j );
            AddEdge( j, x );
        }
        Cnt = 0;
        Dfs1( 1, 0 );
        Cal( Rt[ 1 ], 0 );
        S = A[ Rt[ 1 ] ];
        for( int j = 2; j <= Cnt; ++j ) {
            Cal( Rt[ j ], 0 );
            if( A[ Rt[ j ] ] < S )
                S = A[ Rt[ j ] ];
        }
        if( Map.find( S ) == Map.end() ) Map[ S ] = i;
        printf( "%d\n", Map[ S ] );
    }
    return 0;
}

추천

출처www.cnblogs.com/chy-2003/p/11613061.html