題目鏈結
這是我在學玩 樹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...