题解:CF1800G Symmetree
这真的是紫?
通过对称想到同构,同构又能想到树哈希,对称肯定是需要递归的,那么对于当前递归到的一个点 map 记录分别以 map,看一下对于每一个哈希值的次数是否为偶数,如果有一个哈希值的次数不是偶数,那么此树显然不对称,当
当然,如果这样,那还递归个毛线?直接判断
注意:那唯一的一个哈希值,我们是需要找到所有儿子的哈希值是这个的儿子都要递归一遍,因为分不清哪个是落单的。
多测不清空,爆零两行泪!
时间复杂度
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+5;
vector<int>e[N];
int h[N];
int son[N];
mt19937 r(time(0));
int rr = r();
int s(int x)
{
x^=rr;
x^=(x<<13);
x^=(x>>7);
x^=(x<<17);
x^=rr;
return x;
}
int dfs(int x,int fa)
{
h[x] = 1;
for(int v:e[x])
{
if(v!=fa)
{
h[x]+=s(dfs(v,x));
}
}
return h[x];
}
int flag;
void dfs1(int x,int fa)
{
if(!flag)
{
return;
}
int cnt = 0;
map<int,int>mp;
for(int v:e[x])
{
if(v!=fa)
{
son[++cnt] = v;
mp[h[v]]++;
}
}
int ans = 0,num = 0;
for(auto it = mp.begin();it!=mp.end();it++)
{
ans+=(it->second&1);
if(it->second&1)
{
num = it->first;
}
}
if(ans>1)
{
flag = 0;
return;
}
if(ans == 1)
{
for(int i = 1;i<=cnt;i++)
{
if(h[son[i]] == num)
{
dfs1(son[i],x);
}
}
}
}
signed main()
{
int _;
scanf("%d",&_);
while(_--)
{
int n;
scanf("%d",&n);
for(int i = 1;i<=n;i++)
{
e[i].clear();
}
flag = 1;
for(int i = 1;i<n;i++)
{
int x,y;
scanf("%d %d",&x,&y);
e[x].push_back(y);
e[y].push_back(x);
}
int g = dfs(1,0);
dfs1(1,0);
if(flag)
{
printf("YES\n");
}
else
{
printf("NO\n");
}
}
return 0;
}