# 【ZJOI2017】仙人掌

### 限制与约定

1$\le 5$$\le 10 2\le 2000$$\le 2 \times 10^5$
3
4$\le 10^5$$= n - 1图为一条链 5 6 7 8\le 5 \times 10^5$$\le 10^6$
9
10

### 分析1

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<climits>
#include<vector>
#include<cmath>
#include<map>
#include<set>
#define LL long long

using namespace std;

inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}

char c=nc();int b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

char c=nc();LL b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

{
char c=nc();int len=0;
for(;!(c>='A' && c<='Z');c=nc()) if (c==EOF) return 0;
for(;(c>='A' && c<='Z');s[len++]=c,c=nc());
s[len++]='\0';
return len;
}

for (x=nc();!(x>='A' && x<='Z');x=nc());
}

int wt,ss[19];
inline void print(int x){

if (x<0) x=-x,putchar('-');
if (!x) putchar(48); else {
for (wt=0;x;ss[++wt]=x%10,x/=10);
for (;wt;putchar(ss[wt]+48),wt--);}
}
inline void print(LL x){
if (x<0) x=-x,putchar('-');
if (!x) putchar(48); else {for (wt=0;x;ss[++wt]=x%10,x/=10);for (;wt;putchar(ss[wt]+48),wt--);}
}

int T,n,m,s,flag,v[500010];
vector<int> b[500010];
LL g[500010],f[500010];
const LL mo=998244353;
struct tree
{
int a,b,dfs,low;
}a[500010];
map<int,bool> c[500010];
void init()
{
for (int i=1;i<=n;i++)
b[i].clear(),a[i].dfs=a[i].low=a[i].a=a[i].b=0,c[i].clear();
g[1]=1LL,g[2]=2LL;
for (int i=3;i<=n;i++)
g[i]=(g[i-1]+g[i-2]*(LL)(i-1)%mo)%mo;
}

void dp(int x,int y)
{
v[x]=1;f[x]=1;
int sum=0;
for (int i=0;i<b[x].size();i++)
if (!v[b[x][i]] && !c[x][b[x][i]])
{
dp(b[x][i],y);
f[x]=f[x]*f[b[x][i]]%mo;
sum++;
}
if (x==y) f[x]=f[x]*g[sum]%mo;
else f[x]=f[x]*g[sum+1]%mo;
}

int main()
{
while(T--)
{
int x,y;
init();
for (int i=1;i<=m;i++)
LL res=1;
for(int i=1;i<=n;i++) v[i]=0;
for (int i=1;i<=n;i++)
if (!v[i]) dp(i,i),res=res*f[i]%mo;
print(res);puts("");
}
return 0;
}

### 分析2

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<climits>
#include<vector>
#include<cmath>
#include<map>
#include<set>
#define LL long long

using namespace std;

inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}

char c=nc();int b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

char c=nc();LL b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

{
char c=nc();int len=0;
for(;!(c>='A' && c<='Z');c=nc()) if (c==EOF) return 0;
for(;(c>='A' && c<='Z');s[len++]=c,c=nc());
s[len++]='\0';
return len;
}

for (x=nc();!(x>='A' && x<='Z');x=nc());
}

int wt,ss[19];
inline void print(int x){

if (x<0) x=-x,putchar('-');
if (!x) putchar(48); else {
for (wt=0;x;ss[++wt]=x%10,x/=10);
for (;wt;putchar(ss[wt]+48),wt--);}
}
inline void print(LL x){
if (x<0) x=-x,putchar('-');
if (!x) putchar(48); else {for (wt=0;x;ss[++wt]=x%10,x/=10);for (;wt;putchar(ss[wt]+48),wt--);}
}

int T,n,m,s,flag,v[500010];
vector<int> b[500010];
LL g[500010],f[500010];
const LL mo=998244353;
struct tree
{
int a,b,dfs,low;
}a[500010];
map<int,bool> c[500010];

int dep[500010],dfn[500010],fa[500010],lu[500010],cnt;

void init()
{
for (int i=1;i<=n;i++)
b[i].clear(),a[i].dfs=a[i].low=a[i].a=a[i].b=0,c[i].clear(),dfn[i]=0,dep[i]=0,fa[i]=0;
g[1]=1LL,g[0]=1LL;
for (int i=2;i<=n;i++)
g[i]=(g[i-1]+g[i-2]*(LL)(i-1)%mo)%mo;
}

void dfs(int x,int p)
{
fa[x]=p,dfn[x]=++cnt,dep[x]=dep[p]+1;
for (int i=0;i<b[x].size();i++)
if (!dfn[b[x][i]]) dfs(b[x][i],x);
}

bool check()
{
cnt=0;
dfs(1,0);
int u,v;
memset(lu,0,sizeof(lu));
for (int i=1;i<=n;i++)
for (int j=0;j<b[i].size();j++)
if (i<b[i][j])
{
u=i,v=b[i][j];
if (dfn[u]<dfn[v]) swap(u,v);
while (u!=v)
{
if (lu[u]==2) return false;
lu[u]++,u=fa[u];
}
}
return true;
}

void dp(int x,int y)
{
v[x]=1;f[x]=1;
int sum=0;
for (int i=0;i<b[x].size();i++)
if (!v[b[x][i]] && !c[x][b[x][i]])
{
dp(b[x][i],y);
f[x]=f[x]*f[b[x][i]]%mo;
sum++;
}
if (x==y) f[x]=f[x]*g[sum]%mo;
else f[x]=f[x]*g[sum+1]%mo;
}

void work(int x)
{
for (int i=0;i<b[x].size();i++)
if (v[b[x][i]] && b[x][i]!=fa[x])
{
int y=b[x][i];
c[x][y]=1,c[y][x]=1;
while (x!=y)
{
c[x][fa[x]]=1;c[fa[x]][x]=1;
x=fa[x];
}
return ;
}
else if (!v[b[x][i]])
v[b[x][i]]=1,fa[b[x][i]]=x,work(b[x][i]),v[b[x][i]]=0;
}

int main()
{
while(T--)
{
int x,y;
init();
for (int i=1;i<=m;i++)
}