1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
| #include<algorithm> #include<iostream> #include<iomanip> #include<cstring> #include<cstdlib> #include<climits> #include<vector> #include<cstdio> #include<cmath> #include<queue>
using namespace std;
typedef long long LL;
inline const int Get_Int() { int num=0,bj=1; char x=getchar(); while(!isdigit(x)) { if(x=='-')bj=-1; x=getchar(); } while(isdigit(x)) { num=num*10+x-'0'; x=getchar(); } return num*bj; }
const int maxn=500005,mod=998244353;
int n,m,step=0,Dfn[maxn],Lowlink[maxn],Stack[maxn],Belong[maxn],BCC=0,top=0; LL f[maxn],g[maxn]; bool bj=1,vst[maxn]; vector<int> edges[maxn],edges2[maxn];
void Tarjan(int Now,int fa) { Dfn[Now]=Lowlink[Now]=++step; Stack[++top]=Now; bool flag=0; for(int Next:edges[Now]) { if(Next==fa)continue; if(!Dfn[Next]) { Tarjan(Next,Now); Lowlink[Now]=min(Lowlink[Now],Lowlink[Next]); if(Lowlink[Next]<Dfn[Now]) { if(flag) {bj=0;return;} flag=1; } } else { Lowlink[Now]=min(Lowlink[Now],Dfn[Next]); if(Dfn[Next]<Dfn[Now]) { if(flag) {bj=0;return;} flag=1; } } } if(Dfn[Now]==Lowlink[Now]) { BCC++; int y; do { y=Stack[top--]; Belong[y]=BCC; } while(y!=Now); } }
void TreeDp(int Now,int fa) { f[Now]=vst[Now]=1; for(int Next:edges2[Now]) { if(Next==fa)continue; TreeDp(Next,Now); f[Now]=f[Now]*f[Next]%mod; } f[Now]=f[Now]*g[edges2[Now].size()]%mod; }
void Clear() { for(int i=1; i<=n; i++) { Dfn[i]=vst[i]=0; edges[i].clear(); edges2[i].clear(); } bj=1; BCC=0; }
void AddEdge(int x,int y) {edges[x].push_back(y);} void AddEdge2(int x,int y) {edges2[x].push_back(y);}
int main() { g[0]=g[1]=1; for(int i=2; i<=500000; i++)g[i]=(g[i-1]+g[i-2]*(i-1)%mod)%mod; int t=Get_Int(); while(t--) { Clear(); n=Get_Int(); m=Get_Int(); for(int i=1; i<=m; i++) { int x=Get_Int(),y=Get_Int(); AddEdge(x,y); AddEdge(y,x); } for(int i=1; i<=n; i++)if(!Dfn[i])Tarjan(i,0); if(!bj) { puts("0"); continue; } for(int Now=1; Now<=n; Now++) for(int Next:edges[Now]) if(Belong[Now]!=Belong[Next])AddEdge2(Now,Next); LL ans=1; for(int i=1; i<=n; i++)if(!vst[i])TreeDp(i,0),ans=ans*f[i]%mod; printf("%lld\n",ans); } return 0; }
|