JSOI2016 獨特的樹葉(樹Hash)

2022-07-05 18:00:18 字數 1228 閱讀 5779

題目鏈結

這是我在學玩 樹hash 後來做的一道題,似乎 樹hash 的題很少,我只找到了這一道,但是卻是道省選題,說明省選還是可能出的。

給定兩棵樹,其中一棵為 \(n\) 個節點,另一棵樹是在上一棵樹的基礎上新增了乙個葉子節點構成的(一共有 \(n+1\) 個節點),請你找出新增的是哪個葉子節點,輸出編號最小的那乙個。 (\(n <= 10^5\))

這道題顯然是個樹同構的題目吧,所以需要用到 樹hash。

因為是無根樹,所以我們先利用換根dp求出第一棵樹的每個節點做根時的hash值,用 map 存起來。

然後對於第二棵樹做同樣的操作。

我們發現葉子節點的度數一定是 1,所以我們可以找到哪些是葉子節點,我們發現去掉葉子節點 \(u\) 的整棵樹的hash值就是 \(ha[fa[u]] - base*pri[1]\)。

然後我們就可以在 map 裡面找是否可以匹配。

// by longdie 

#include #define ull unsigned long long

using namespace std;

const int n = 1e5 + 5;

const ull base = 1;

mapp;

int n, vis[n*20], tot, pri[n];

struct tree e[n<<1];

void add(int x, int y) , head[x] = cnt, d[x]++;

} void dfs0(int u, int fa)

} void dfs1(int u, int fa)

for(register int i = head[u], v; i; i = e[i].next)

} void solve(int m)

dfs0(1, 0);

f[1] = ha[1];

dfs1(1, 0);

} } a, b;

signed main()

} a.solve(n);

for(register int i = 1; i <= n; ++i)

b.solve(n + 1);

for(register int i = 1; i <= n + 1; ++i)

return 0;

}

JSOI2016 獨特的樹葉(樹雜湊)

這個題只要求出以每個點為根的有根 無標號 樹的hash值就好了。我以前的樹雜湊是把樹轉為括號序,這個太麻煩了。一種方法是每個點的權值定義為siz,找到乙個dfs序,使得經過的點的權值字典序組最小。這個對於這道題也不方便,因為換根是可能需要字首和字尾和搞。在網上看到一種的hash是這個 f x 1 s...

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...