Untitled
unknown
c_cpp
2 years ago
3.7 kB
13
Indexable
#include<bits/stdc++.h>
#define ll long long
#define LL long long
#define MOD1 (987777733LL)
#define MOD2 (1010101333LL)
#define endl '\n'
#define SZ(x) ((int)x.size())
#define MXN (1000005)
#define INF (1e9)
#define rep(i,l,r) for(int i=l;i<r;i++)
using namespace std;
mt19937 gen(880907);
template<typename T1,typename T2>
ostream& operator<<(ostream& out,const pair<T1,T2>& p){
out<<p.first<<" "<<p.second;
return out;
}
// #define DEBUG
template<typename T1,typename T2>
pair<ll,ll> operator*(pair<T1,T1> lhs,pair<T2,T2> rhs){
pair<ll,ll> ret;
ret.first = lhs.first*rhs.first%MOD1;
ret.second = lhs.second*rhs.second%MOD2;
return ret;
}
template<typename T1,typename T2>
pair<ll,ll> operator+(pair<T1,T1> lhs,pair<T2,T2> rhs){
pair<ll,ll> ret;
ret.first = (lhs.first+rhs.first)%MOD1;
ret.second = (lhs.second+rhs.second)%MOD2;
return ret;
}
//rotate(begin(s),begin(s)+minRotation(s),end(s))
int minRotation(vector<ll> s) {
int a = 0, N = s.size();
for(int i=0;i<N;i++) s.push_back(s[i]);
rep(b,0,N) rep(k,0,N) {
if(a+k == b || s[a+k] < s[b+k]){
b += max(0, k-1); break;
}
if(s[a+k] > s[b+k]) {
a = b; break;
}
}
return a;
}
int n,o;
int sz[MXN];
bool flag,finish;
bool v[MXN],c[MXN];
bool isprime[20000007];
vector<ll> val,primes;
vector<int> cycle;
vector<vector<int>> edge;
set<vector<ll>> ans;
void dfs(int x,int f){
if(finish) return;
if(v[x]){
flag=1;
o=x;
return;
}
v[x]=1;
for(auto i:edge[x]){
if(i==f) continue;
dfs(i,x);
if(flag) break;
}
if(finish) return;
if(flag){
cycle.push_back(x);
c[x]=1;
if(x==o) finish=1;
}
}
pair<ll,ll> Hash(int x,int f){
pair<ll,ll> ret=make_pair(0,0);
vector<pair<ll,ll>> h;
sz[x]=1;
for(auto i:edge[x]){
if(i==f||c[i]) continue;
h.push_back(Hash(i,x));
sz[x]+=sz[i];
}
sort(h.begin(),h.end());
for(auto i:h){
ret=ret*make_pair(primes[sz[x]],primes[sz[x]])+i;
}
ret = ret*make_pair(primes[sz[x]],primes[sz[x]])+make_pair(1,1);
val[x] = ret.first*ret.second;
return ret;
}
void build(){
for(ll i=2;i<=20000000;i++){
if(isprime[i]) continue;
primes.push_back(i);
for(ll j=i*i;j<=20000000;j+=i){
isprime[j]=1;
}
}
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
build();
shuffle(primes.begin(),primes.end(),gen);
int t; cin>>t;
while(t--){
cin>>n;
ans.clear();
for(int i=0,m;i<n;i++){
cin>>m;
val.clear();val.resize(m);
edge.clear();edge.resize(m);
for(int j=0,a,b;j<m;j++){
cin>>a>>b;
edge[a-1].push_back(b-1);
edge[b-1].push_back(a-1);
}
flag=finish=0;
for(int j=0;j<m;j++) c[j]=v[j]=0;
cycle.clear();
o=-1;
dfs(0,0);
vector<ll> tmp1,tmp2;
for(auto j:cycle){
Hash(j,j);
tmp1.push_back(val[j]);
}
rotate(tmp1.begin(),tmp1.begin()+minRotation(tmp1),tmp1.end());
tmp2=tmp1;
reverse(tmp2.begin(),tmp2.end());
rotate(tmp2.begin(),tmp2.begin()+minRotation(tmp2),tmp2.end());
ans.insert(min(tmp1,tmp2));
}
cout<<ans.size()<<endl;
}
return 0;
}Editor is loading...