JAG Practice2016-E Similarity of Subtrees- hash

来源:互联网 发布:淘宝店铺产品布局 编辑:程序博客网 时间:2024/05/21 14:49

https://acm.bnu.edu.cn/v3/statments/jag2016.pdf

题意:

num(T1,d)  为树T1在深度为d这一层的子节点数量

定义 两棵树相似 的条件为

对所有的d, S(T,d) equals S(T ′ ,d) 


从叶子节点开始bfs,每个节点的相似度信息可以hash成一个数。

从当前节点开始去更新父亲节点的相似度信息

只有当一个节点的所有儿子都访问完了(也即得到了自身完整的相似度信息),才进入队列


在每一层计算一次,具有相同相似度的节点对答案的贡献为 C(X,2)

#include <cstdio>#include <cmath>#include <cstring>#include <string>#include <algorithm>#include <iostream>#include <queue>#include <map>#include <set>#include <vector>using namespace std;const int N=100005;typedef long long ll;vector<int >mp[N];int son_num[N];int son_come[N];unsigned long long  hash_val[N];int fa[N];void dfs(int x,int f){    for (int i=0; i<mp[x].size(); i++)    {        int v=mp[x][i];        if (v==f)continue;        fa[v]=x;        son_num[x]++;        dfs(v,x);    }}map<unsigned long long   ,int> vis;map<unsigned long long  ,int> ::iterator it;struct node{    int dep,x;    node() {}    node(int a,int b)    {        x=a,dep=b;    }};queue<node> q;int main(){    int n,u,v;    cin>>n;    for (int i=1; i<n; i++)    {        scanf("%d%d",&u,&v);        mp[u].push_back(v);        mp[v].push_back(u);    }    dfs(1,0);    for (int i=1; i<=n; i++)        if (!son_num[i]) q.push(node(i,1));    ll ans=0;    while(!q.empty())    {        int sz=q.size();        vis.clear();        for (int i=1; i<=sz; i++)        {            node tp=q.front();            q.pop();            hash_val[tp.x]+=239;            vis[hash_val[tp.x]]++;            int f=fa[tp.x];            hash_val[f]+=hash_val[tp.x]*239;            son_come[f]++;            if (son_come[f]==son_num[f])                q.push(node(f,tp.dep+1));        }        for (it=vis.begin();it!=vis.end();it++)        ans+= 1LL*it->second*(it->second-1)/2;    }    printf("%lld\n",ans);    return 0;} 


0 0
原创粉丝点击