&& хэш дерева изоморфны учебник [BJOI2015] Дерево

Ссылка на тему

Внедренный дерево хэш

Дискретная математика описание хеш - дерева в здесь . Мы можем смотреть.

Определение, есть ли корневое дерево со структурой, можно считать корневым кодирование дерева. Процесс кодирования, требуется, чтобы сохранить дерево морфологические признаки, игнорируя при этом порядок различных суб-дерева. Первый взгляд на этот метод:

Вы можете сделать кодирование дерева является строка \ (T \) .

Для точки \ (U \) , сначала найти \ (U \) все \ (son_u \) кодирование \ (son_u Р- {} \) , а затем их кодируют в лексикографическом порядке от маленьких до больших , чтобы дать \ (g_ { . 1 \ К} cdots \) . Тогда \ (f_u = "0" + \ СУММА \ Пределы G_i +». 1" \) .

Таким образом , \ (Т \) кодируется как корневой узел кодирования.

Вы можете проверить правильность этого алгоритма декодирования пути.

Этот код просто цифры, не считается хэш дерева. Этот код гарантирует правильность. В самом деле, когда мы используем , как правило , не может и не позволить этому (пространство слишком много времени). Как правило , мы по модулю операции и методы будут использовать значение. На самом деле, стоимость операции , чтобы удовлетворить как можно больше 保留树形态的特征,同时忽略子树顺序的不同. Сложение, 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