&&ハッシュツリー同型チュートリアル[BJOI2015]ツリー

トピックリンク

根ざした木のハッシュ

でハッシュツリーの離散数学説明をここに私たちは見ることができます。

構造のルート権限を取得し、ツリーがあるかどうかを決定する、それが根付いた木のコーディングとみなすことができます。異なるサブツリーの順序を無視して符号化処理は、ツリーの形態学的特徴を保持する必要があります。まず、この方法を見てみましょう。

あなたは木のコーディングが文字列であることを確認したいと思うかもしれ\(T \)

ポイントのために\(U \) 最初の検索\を(U \)すべて\(son_u \)エンコーディング\(son_u F_ {} \) 及びこれらが与える小から大まで辞書式順序で符号化\を(G_ { 1 \ K} cdots \) その後、\(f_u = "0" + \ SUM \ + G_iを制限します」。1" \)

そう\(T \)コードのルートノードとして符号化されます。

あなたは道を復号することによって、このアルゴリズムの正しさを検証することができます。

このコードは、数字だけであるハッシュツリーとはみなされません。このコードは正確さを保証します。実際には、私たちが通常使用している場合と、(スペースがあまりにも多くの時間である)、この許可することはできませんしません。私たちは、通常の操作を法および方法は値を使用します。実際には、演算の値は、できるだけ多くを満たすために保留树形态的特征,同时忽略子树顺序的不同さらに、XOR、ソートなどが可能です。

メソッドのハッシュツリーは、非常に大きいOIwikiの3つの一般的な方法があります

無根樹ハッシュ

一般に、ルート無根木を選択し、それによって無根ツリーをコード達成、ルート付きツリーに変わります。選択された数の一般的なルートセンター。選択されたコードの小さな中央ルート上の2つのセンターがある場合。真実のためにほぼ同じハッシュです。

データ範囲は、非常に小さいので、この質問については、直接暴力コーディングので、マップを再宣告することができます。

#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