CF 718 D Andrew and Chemistry 题解

CF 718 D Andrew and Chemistry 题解

可以发现如果在\(u\)添加一个点形成树\(T\)和在\(v\)添加一个点形成的树\(T'\)本质相同。

也就是说\(u\)\(v\)等价(以\(u\)\(v\)为根的哈希值相等)。

直接换根dp即可。

#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(time(0))
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
//inline int read(){
//    int x=0;
//    char ch=getchar();
//    while(ch<'0'||ch>'9'){
//        ch=getchar();
//    }
//    while(ch>='0'&&ch<='9'){
//        x=(x<<1)+(x<<3)+(ch^48);
//        ch=getchar();
//    }
//    return x;
//}
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
const int MAXN=1e5+1;
int n;
vector<int> g[MAXN];
map<unsigned LL ,int> ans;
unsigned LL ky[MAXN];
int siz[MAXN];
unsigned LL ran[MAXN];
void trans(int now,int pre,int sz){
    ky[now]=1;
    vector<pair<unsigned LL,int> > v;
    for(auto it:g[now]) if(it!=pre) v.PB(II(ky[it],siz[it]));
    sort(ALL(v));
    rep(i,v.size()){
        ky[now]+=v[i].FIR*ran[v[i].SEC];
    }
}
void dfs(int now,int pre){
    siz[now]=1;
    for(auto it:g[now]) if(it!=pre) dfs(it,now),siz[now]+=siz[it];
    trans(now,pre,siz[now]);
}
void mv(int now,int pre){
    if(g[now].size()<4)
    ans[ky[now]]=1;
    for(auto it:g[now]) if(it!=pre){
        unsigned LL mem1,mem2;
        mem1=ky[now];
        mem2=ky[it];
        int A,B;
        A=siz[now];
        B=siz[it];
        siz[now]=n-B;
        siz[it]=n;
        trans(now,it,A-B);
        trans(it,0,n);
        mv(it,now);
        siz[now]=A;
        siz[it]=B;
        ky[now]=mem1;
        ky[it]=mem2;
    }
}
bool check(int x){
    for(int i=2;i*i<=x;i++){
        if(x%i==0) return 0;
    }
    return 1;
}
int main(){
    vector<int> pr;
    int now=2;
    while(pr.size()<1e5){
        if(check(now)) pr.PB(now);
        now++;
    }
    rb(i,1,1e5) ran[i]=pr[i-1];
    scanf("%d",&n);
    rb(i,1,n-1){
        int u,v;
        scanf("%d%d",&u,&v);
        g[u].PB(v);
        g[v].PB(u);
    }
    dfs(1,0);
    mv(1,0);
    cout<<ans.size()<<endl;
    return 0;
}
posted @ 2021-08-24 00:13  WWW~~~  阅读(44)  评论(0编辑  收藏  举报