import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.util.ArrayDeque; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.NoSuchElementException; import java.util.Random; class DJSet { int n; int[] upper; public DJSet(int n) { this.n=n; upper=new int[n]; Arrays.fill(upper, -1); } int root(int x) { return upper[x]<0?x:(upper[x]=root(upper[x])); } boolean equiv(int x,int y) { return root(x)==root(y); } void unite(int x,int y) { x=root(x);y=root(y); if (x==y) return; if (upper[x]=2) ++ret; return ret; } } public class Main { public static void main(String[] args) { new Main().run(); } final long MOD=998244353; final int MAX=100000; long[] fc=new long[MAX]; long[] ifc=new long[MAX]; long[] inv=new long[MAX]; long[] p2=new long[MAX]; { fc[0]=fc[1]=ifc[0]=ifc[1]=inv[0]=inv[1]=p2[0]=1; for (int i=2;i>i)%2==1) { ++deg[a[i]]; ++deg[b[i]]; ds.unite(a[i], b[i]); } int d1=0,d2=0,c=0; for (int i=0;i=3) continue out; if (deg[i]==1) ++d1; else if (deg[i]==2)++d2; } for (int i=0;i=2) c+=ds.sz(i); if (d1==0 && d2==0) { ans=(ans+parity*dp[0][c][0]%MOD)%MOD; } else if (d1==0 && ds.num()==1) { ans=(ans+parity)%MOD; } else if (Integer.bitCount(s)==1) { ans=(ans+parity*dp[1][c][1]%MOD)%MOD; } else if (d1==2*ds.num()) { ans=(ans+parity*dp[2][c][ds.num()]%MOD)%MOD; } } return ans; } long exact(int N,int[] a,int[] b) { int M=a.length; HashSet> set=new HashSet<>(); for (int i=0;i dq=new ArrayDeque<>(); for (int i=0;i>dst)%2==1) continue; if (set.contains(List.of(s.t,dst))) continue; State next=s.copy(); if (dst==s.s) { ans[Integer.bitCount(s.vis)]++; } else { next.t=dst; next.vis|=1<> set=new HashSet<>(); for (int i=0;i Integer.MAX_VALUE) throw new NumberFormatException(); return (int) nl; } public double nextDouble() { return Double.parseDouble(next());} }