這個題只要求出以每個點為根的有根(無標號)樹的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...