板子题 dsu 不同的是 维护什么样的值
# include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 200010;
int n;
vector<int>e[N];
int cnt[N];//每个颜色出现次数
int maxcnt;//众数出现次数
LL sumcnt,ans; //众数的和 众数出现多少次
int l[N],r[N],id[N],sz[N],hs[N],tot,c[N];
void dfs(int u,int f){
l[u] = ++tot;
id[tot] = u;
sz[u] = 1;
hs[u] = -1;
for ( auto v : e[u]){
if (v == f) continue;
dfs(v,u);
// 一路递归上去
sz[u] += sz[v];
if(hs[u] == -1 || sz[v] > sz[hs[u]]){
hs[u] = v;
}
}
// 结束的dfs序列
r[u] = tot;
}
void dfs2(int u,int f ,bool keep){
for(auto v :e[u]){
if ( v!= f && v!=hs[u]){
dfs2(v,u,false);
}
}
if(hs[u] != -1){
dfs2(hs[u],u,true);
// 重儿子的集合
}
auto add =[&](int x){
x = c[x];
cnt[x]++;
if(cnt[x] > maxcnt) maxcnt = cnt[x],sumcnt=0;
// 这里有问题 应该是else if 原本是统计颜色的编号所以 改完之后 要立即加上 ,但是这个不用 判断 如果相等在家家,
//这样导值不对 不然我可以令他等于0
if (cnt[x] == maxcnt) sumcnt++;
};
auto del = [&](int x){
x = c[x];
cnt[x]--;
};
for (auto v : e[u]){
if(v!=f && v!= hs[u]){
for(int x =l[v];x<=r[v];x++)
add(id[x]);
}
}
// u本身加入
add(u);
if (maxcnt*sumcnt == sz[u]){
ans++;
}
if(!keep){
maxcnt = 0;
sumcnt = 0;
for(int x = l[u];x<=r[u];x++){
del(id[x]);
}
}
}
int main(){
scanf("%d",&n);
int a,b;
for(int i = 1;i<=n;i++){
scanf("%d%d",&a,&b);
c[i] = a;
if (b!=0){
e[b].push_back(i);
e[i].push_back(b);
}
}
dfs(1,0);
dfs2(1,0,false);
cout<<ans<<endl;
return 0;
}