JSOI2016 獨特的樹葉(樹雜湊)

2022-05-01 05:00:10 字數 1359 閱讀 4583

這個題只要求出以每個點為根的有根(無標號)樹的hash值就好了。

我以前的樹雜湊是把樹轉為括號序,這個太麻煩了。

一種方法是每個點的權值定義為siz,找到乙個dfs序,使得經過的點的權值字典序組最小。

這個對於這道題也不方便,因為換根是可能需要字首和字尾和搞。

在網上看到一種的hash是這個:

\(f[x]=(1+\sum_ f[y]*p[siz[y]](質數))~mod~mo\)

感覺還不錯,因為是加法,所以好換根。

但是可能在樹很小的時候容易錯。

code

#include#define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)

#define ff(i, x, y) for(int i = x, _b = y; i < _b; i ++)

#define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)

#define ll long long

#define pp printf

#define hh pp("\n")

using namespace std;

const ll mo = 23333333333333333;

ll mul(ll x, ll y)

namespace sub1

} }}using sub1 :: p;

const int n = 1e5 + 5;

struct nod

int fa[n], siz[n];

ll f[n];

void dg(int x)

} ll g[n], s[n], s2[n];

void dfs(int x)

s[x] = f[x];

s2[x] = f[to[fi[x]]];

for(int i = fi[x]; i; i = nt[i]) if(to[i] != fa[x])

siz[0] = siz[x];

for(int i = fi[x]; i; i = nt[i]) if(to[i] != fa[x])

}} e1, e2;

int n, x, y;

mapbz;

int main()

fo(i, 1, n)

e1.dg(1); e1.dfs(1);

e2.dg(1); e2.dfs(1);

fo(i, 1, n) bz[e1.s[i]] = 1;

fo(i, 1, n + 1) if(e2.r[i] == 1 && bz[e2.s2[i]])

}

JSOI2016 獨特的樹葉(樹Hash)

題目鏈結 這是我在學玩 樹hash 後來做的一道題,似乎 樹hash 的題很少,我只找到了這一道,但是卻是道省選題,說明省選還是可能出的。給定兩棵樹,其中一棵為 n 個節點,另一棵樹是在上一棵樹的基礎上新增了乙個葉子節點構成的 一共有 n 1 個節點 請你找出新增的是哪個葉子節點,輸出編號最小的那乙...

JSOI2016 獨特的樹葉

點此看題 其實就是判斷樹同構,然後自然聯想到了樹has hhash hash 簡單介紹一下樹雜湊的方法,我們先求出子樹的has hhash hash 值g i g i g i 我用的是質數 自然溢位的方式,設p i p i p i 為第i ii個質數,那麼轉移 g u 1 g v p siz v g...

JSOI2016 獨特的樹葉

仙題 1.我們發現如果能夠求出來 a 樹中任何乙個點當根的時候的 hash 值,那麼就可以求出答案了。然後你隨便寫一寫 hash 策略改成 xor 發現 xor 的逆運算就是 xor 好啊!換根 dp 直接求出我們需要的,然後放到 set 去就行了。include include include i...