點此看題
其實就是判斷樹同構,然後自然聯想到了樹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[u]=1+\sum g[v]\times p[siz[v]]
g[u]=1
+∑g[
v]×p
[siz
[v]]
那麼對於u
uu點為根的雜湊值hs[
u]
hs[u]
hs[u
],就可以再跑一遍dfs
dfsdf
s求出了。
回到此題,對於第一棵樹,我們可以把每個點為根的雜湊值放進map
mapma
p中方便第二棵樹查詢。然後對於第二棵樹,我們列舉他的乙個葉子,然後看刪去這個葉子後他父親為根的has
hhash
hash
值,注意1
11為根的話是需要特判的(我們定的根有可能是葉子),然後去map
mapma
p裡面找有沒有這個has
hhash
hash
值就可以判斷是否合法。
我的常數比較優秀,在 luo
gu
\tt luogu
luog
u 上可以操到 ran
k2
\tt rank2
rank
2
#include
#include
using
namespace std;
const
int m =
200005
;#define ull unsigned long long
intread()
int cnt,p[m]
;bool vis[
15*m]
; map<
int,ull> mp;
struct edge
;void
init
(int n)}}
struct tree
,f[u]
=tot;
e[++tot]
=edge
,f[v]
=tot;
}dfs(1
,0);
dfs2(1
,0);
}void
dfs(
int u,
int fa)
}void
dfs2
(int u,
int fa)
}}t1,t2;
intmain()
}for
(int i=
2;i<=t2.n;i++)if
(t2.siz[i]==1
)//找葉子
}}
JSOI2016 獨特的樹葉
仙題 1.我們發現如果能夠求出來 a 樹中任何乙個點當根的時候的 hash 值,那麼就可以求出答案了。然後你隨便寫一寫 hash 策略改成 xor 發現 xor 的逆運算就是 xor 好啊!換根 dp 直接求出我們需要的,然後放到 set 去就行了。include include include i...
JSOI2016 獨特的樹葉
有一顆大小為 n 的樹 a 現加上乙個節點並打亂編號,形成樹 b 詢問加上的節點最後編號是多少?判斷樹的同構顯然需要樹雜湊。可以先將樹 a 中以每個節點為根的雜湊值算出來存進乙隻 unordered set 中,然後在樹 b 中隨便找乙個不是葉節點的節點為根,列舉去掉乙個葉節點,看根的 hash 值...
JSOI2016 獨特的樹葉(樹雜湊)
這個題只要求出以每個點為根的有根 無標號 樹的hash值就好了。我以前的樹雜湊是把樹轉為括號序,這個太麻煩了。一種方法是每個點的權值定義為siz,找到乙個dfs序,使得經過的點的權值字典序組最小。這個對於這道題也不方便,因為換根是可能需要字首和字尾和搞。在網上看到一種的hash是這個 f x 1 s...