HDU5732 Subway树重心 树哈希
Posted kikokiko
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU5732 Subway树重心 树哈希相关的知识,希望对你有一定的参考价值。
题意:
给出两棵大小为(N)的同构树,要求输出对应的节点
(Nle 10^5)
题解:
由于重心最多只有两个,找到重心之后以重心为根进行树哈希,找到相同哈希值的根之后递归输出即可
输出儿子的时候要先对哈希值排序,保证递归进去的儿子节点也是同构的
这里用的哈希方法是(f[u] = 1 + sum_{vin son_u}f[v]cdot prime[sz[v]])
view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
typedef uint64_t ull;
const int MAXN = 2e5+7;
vector<int> prime;
void sieve(){
vector<bool> pm(MAXN,true);
for(int i = 2; i < MAXN; i++){
if(pm[i]) prime.push_back(i);
for(int j = 0; j < (int)prime.size(); j++){
if(i*prime[j]>=MAXN) break;
pm[i*prime[j]] = false;
if(i%prime[j]==0) break;
}
}
}
int n;
struct Tree{
vector<int> G[MAXN];
map<string,int> msk;
string name[MAXN];
int sz[MAXN],maxsz[MAXN];
ull hashval[MAXN];
int tot,root;
void clear(){
for(int i = 1; i <= tot; i++) G[i].clear();
tot = 0;
msk.clear();
}
int getID(string &s){
if(!msk.count(s)){
msk[s] = ++tot;
name[tot] = s;
}
return msk[s];
}
void dfs(int u, int f){
sz[u] = 1; maxsz[u] = 0;
for(int v : G[u]){
if(v==f) continue;
dfs(v,u);
sz[u] += sz[v];
maxsz[u] = max(maxsz[u],sz[v]);
}
maxsz[u] = max(maxsz[u],tot-sz[u]);
}
void getHash(int u, int f){
sz[u] = 1;
hashval[u] = 1ull;
for(int v : G[u]){
if(v==f) continue;
getHash(v,u);
sz[u] += sz[v];
hashval[u] += hashval[v] * prime[sz[v]];
}
}
}tr[2];
void match(int u0, int u1, int f0, int f1){
cout << tr[0].name[u0] << ‘ ‘ << tr[1].name[u1] << endl;
tr[0].hashval[f0] = UINT64_MAX;
tr[1].hashval[f1] = UINT64_MAX;
sort(tr[0].G[u0].begin(),tr[0].G[u0].end(),[&](const int &x, const int &y){
return tr[0].hashval[x] < tr[0].hashval[y];
});
sort(tr[1].G[u1].begin(),tr[1].G[u1].end(),[&](const int &x, const int &y){
return tr[1].hashval[x] < tr[1].hashval[y];
});
int m = (int)tr[0].G[u0].size() - (f0==0?0:1);
for(int i = 0; i < m; i++)
match(tr[0].G[u0][i],tr[1].G[u1][i],u0,u1);
}
void solve(){
tr[0].clear(); tr[1].clear();
for(int t = 0; t < 2; t++){
for(int i = 1; i < n; i++){
string s1, s2;
cin >> s1 >> s2;
int u = tr[t].getID(s1);
int v = tr[t].getID(s2);
tr[t].G[u].push_back(v);
tr[t].G[v].push_back(u);
}
}
tr[0].dfs(1,0);
int hsz = *min_element(tr[0].maxsz+1,tr[0].maxsz+1+n);
for(int i = 1; i <= n; i++){
if(tr[0].maxsz[i]==hsz){
tr[0].root = i;
break;
}
}
tr[0].getHash(tr[0].root,0);
ull hax = tr[0].hashval[tr[0].root];
tr[1].dfs(1,0);
for(int i = 1; i <= n; i++){
if(tr[1].maxsz[i]==hsz){
tr[1].getHash(i,0);
if(hax==tr[1].hashval[i]){
tr[1].root = i;
break;
}
}
}
match(tr[0].root,tr[1].root,0,0);
}
int main(){
____();
sieve();
while(cin >> n) solve();
return 0;
}
以上是关于HDU5732 Subway树重心 树哈希的主要内容,如果未能解决你的问题,请参考以下文章