المپدیا

دانش‌نامه‌ی المپیاد کامپیوتر ایران

ابزار کاربر

ابزار سایت


آموزش:الگوریتم‌های تکمیلی:یک‌ریختی درخت‌ها

روش

درخت را از دو راس یا تک راس مرکز آن، آویزان کرده و آن را $Hash$ می‌کنیم. دو درخت یک‌ریخت‌اند اگر مقدار hash_value آن دو برابر باشد.
ساختار اصلی کد ارائه شده همان الگوریتم پیدا کردن مرکز درخت است که در میان آن همواره hash_value زیردرخت هر راس نیز محاسبه شده است.

کد یافتن hash_value یک درخت

const int Maxn = 1e5 + 3, M = 1e9 + 9;
const long long Z = 239;
int n, deg[Maxn], hash_value[Maxn], h[Maxn];
vector < int > adj[Maxn];

int getHash () {
	int center[2] = {0, 0};
	queue < int > q;
	for(int i = 1; i <= n; ++i)
		if (deg[i] == 1) {
			q.push(i);
			h[i] = 1;
		}
	while(!q.empty()) {
		int v = q.front();
		q.pop();

		int par = 0;
		vector < int > hash_child;
		for(int u: adj[v]) {
			if (h[u] && h[u] < h[v])
				hash_child.push_back(hash_value[u]);
			else if (--deg[u] == 1) {
				q.push(u);
				h[u] = h[v] + 1;
			}
			if (h[u] > h[v])
				par = u;
		}
		if (!par) {
			center[1] = center[0];
			center[0] = v;
		}
		sort(hash_child.begin(), hash_child.end() );
		hash_value[v] = ((adj[v].size() * Z % M) * h[v]) % M;
		for(int h: hash_child)
			hash_value[v] = (hash_value[v] * Z + h) % M;
	}

	if (hash_value[center[1]] > hash_value[center[0]])
		swap (center[0], center[1]);
	return (hash_value[center[1]] * Z + hash_value[center[0]]) % M;
}

ابزار صفحه