题意:变换是一个排列f,f[i]为把i变为f[i],(i<=1e6)
有n(n<=1e5)个gym,要求种类经过f变换后:每个gym中每个种类个数:变化前和变换后相等,问有多少种合理变换f?
容易发现:若x经过变换后为y 则每个gym中x个数是等于y的个数(不好算直接统计出相等的种类).->x所在的gym集合等于y所在的gym集合 (vector[i] 种类i的的gym集合 sort后即可比较)
//若把能相互变换的放入一个数据结构中,则该块方法数为S!(S为该块的个数),最后每块方法数相乘即可
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int N=1e6+20;
vector<int> a[N];//a[i]种类i的gym集合
int main()
{
int n,m;
while(cin>>n>>m)
{
for(int i=1;i<=n;i++)
{
int num;
scanf("%d",&num);
while(num)
{
int x;
scanf("%d",&x);
a[x].push_back(i);//
num--;
}
}
sort(a+1,a+1+m);//为了比较种类所在集合是否相等
ll t=1,ans=1;
for(int i=2;i<=m;i++)
{
if(a[i]==a[i-1])
{
t++;
ans=(ans*t)%mod;
}
else
t=1;
}
cout<<ans<<endl;
for(int i=1;i<=n;i++)
a[i].clear();
}
return 0;
}