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 118 119 120 121
| const int N = 3e4 + 5,M = 1e6 + 5,K = 75,P = 998244353; inline void Plus(int &x,const int &y) { x += y;if(x >= P) x -= P;} inline int qpow(int a,int b) { int res = 1;while(b) { if(b&1) res = 1ll * res * a % P;a = 1ll * a * a % P;b >>= 1;} return res;} int n,m,k; int fir[N],nxt[M],to[M],ect = 1; int dfn[N],low[N],cut[M],dfstime; int e[K][K]; inline void addedge(int u1,int v1) { nxt[++ect] = fir[u1];fir[u1] = ect;to[ect] = v1; } inline int Det(int num) { static int A[K][K]; for(int i = 1;i <= num;i++) for(int j = 1;j <= num;j++) A[i][j] = e[i][j]; int ans = 1; for(int i = 1;i <= num;i++) { if(!A[i][i]) for(int j = i + 1;j <= num;j++) if(A[j][i]) { for(int k = 1;k <= num;k++) swap(A[i][k],A[j][k]); ans = P - ans;break; } if(!A[i][i]) return 0; ans = 1ll * ans * A[i][i] % P; int inve = qpow(A[i][i],P - 2); for(int j = 1;j <= num;j++) if(j != i) { int div = 1ll * A[j][i] * inve % P; for(int k = i;k <= num;k++) Plus(A[j][k],P - 1ll * div * A[i][k] % P); } } return ans; } void tarjan(int x,int from) { dfn[x] = low[x] = ++dfstime; for(int i = fir[x],y;y = to[i],i;i = nxt[i]) if(y != from) { if(!dfn[y]) { tarjan(y,x); low[x] = min(low[x],low[y]); if(low[y] > dfn[x]) cut[i] = cut[i ^ 1] = true; } else low[x] = min(low[x],dfn[y]); } } int co[N],dp[N][2]; vector<int> vs[N]; void dfs0(int x,int col) { co[x] = col;vs[col].push_back(x); for(int i = fir[x],y;y = to[i],i;i = nxt[i]) if(!co[y] && !cut[i]) dfs0(y,col); } int pre[N],suf[N]; int e2[K][K]; int c0[N]; void DP(int x,int fa) { int num = 2 * vs[x].size(); int cnt = vs[x].size(); for(int i = 0;i < cnt;i++) for(int t = fir[vs[x][i]],v;v = to[t],t;t = nxt[t]) if(co[v] != fa && co[v] != x) DP(co[v],x); for(int i = 1;i <= num;i++) for(int j = 1;j <= num;j++) e[i][j] = 0; for(int i = 0;i < vs[x].size();i++) for(int t = fir[vs[x][i]],j;j = to[t],t;t = nxt[t]) { auto pp = std::find(vs[x].begin(),vs[x].end(),j); if(pp != vs[x].end()) e[i + 1][pp - vs[x].begin() + 1]++; } for(int i = 0;i < vs[x].size();i++) { int u = vs[x][i]; int s0 = 1,s1 = 0; vector<int> son;son.push_back(0); for(int t = fir[u],v;v = to[t],t;t = nxt[t]) { if(co[v] == fa || co[v] == x) continue; son.push_back(co[v]); s0 = 1ll * s0 * dp[co[v]][0] % P; } pre[0] = 1; for(int i = 1;i < son.size();i++) pre[i] = 1ll * pre[i - 1] * dp[son[i]][0] % P; suf[(int)son.size()] = 1; for(int i = (int)son.size() - 1;i >= 1;i--) suf[i] = 1ll * suf[i + 1] * dp[son[i]][0] % P; for(int i = 1;i < son.size();i++) Plus(s1,1ll * dp[son[i]][1] * pre[i - 1] % P * suf[i + 1] % P); int p1 = i + 1,p2 = i + vs[x].size() + 1; e[p2][p2] = s0; e[p1][p2] = s1;e[p2][p1] = 1; c0[u] = s0; } dp[x][0] = Det(num); int psf = -1; for(int i = 0;i < cnt;i++) for(int t = fir[vs[x][i]],j;j = to[t],t;t = nxt[t]) if(co[j] == fa) { psf = i + 1;break;} for(int i = 1;i <= num;i++) if(i != psf && i != psf + cnt) for(int j = 1;j <= num;j++) if(j != psf && j != psf + cnt) { int p1 = i - (i >= psf) - (i >= psf + cnt); int p2 = j - (j >= psf) - (j >= psf + cnt); e2[p1][p2] = e[i][j]; } num -= 2; for(int i = 1;i <= num;i++) for(int j = 1;j <= num;j++) e[i][j] = e2[i][j]; dp[x][1] = 1ll * Det(num) * (psf > 0 ? c0[vs[x][psf - 1]] : 1) % P; } int main() { read(n);read(m);read(k); for(int i = 1;i <= m;i++) { int u,v; read(u);read(v); addedge(u,v);addedge(v,u); } tarjan(1,0); int col = 0; for(int i = 1;i <= n;i++) if(!co[i]) ++col,dfs0(i,col); DP(1,0); cout << dp[1][0] << endl; return 0; }
|