根ざした木のハッシュ
でハッシュツリーの離散数学説明をここに。私たちは見ることができます。
構造のルート権限を取得し、ツリーがあるかどうかを決定する、それが根付いた木のコーディングとみなすことができます。異なるサブツリーの順序を無視して符号化処理は、ツリーの形態学的特徴を保持する必要があります。まず、この方法を見てみましょう。
あなたは木のコーディングが文字列であることを確認したいと思うかもしれ\(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;
}