vector<mint> dp(1 << N, 0); // dp[vertex mask] = 染色mask <= K的方案数 // dp[c]=f^c=convolution(dp[c-1],f) dp[0] = 1; mint ans = 0; mint bin = 1; // binom(K,c) rep(c,1,N+1){ // 颜色种数c vector<mint> ndp(1 << N); // 子集遍历O(3^N) rep(msk,0,1<<N) for(int j=msk;j;j=(j-1)&msk) ndp[msk] += dp[msk-j] * f[j]; swap(dp, ndp); bin *= (K + 1 - c); bin /= c; ans += dp.back() * bin; // binom(K,c) (f^c)(1<<N) } return ans; }
mint calc(int N, int K, vector<pair<int, int>> uv){ // 去掉度 <= 3 的点 for (auto& [u, v] : uv) if (u == v) return0; if (N == 0) return1; // 空集 for (auto& [u, v] : uv) if (u > v) swap(u,v); // 为了去重边 sort(begin(uv), end(uv)); uv.erase(unique(begin(uv), end(uv)), end(uv)); auto ch = [&](int u, int v) { for (auto& [a, b] : uv) { // 交换点 u,v if (a == u or a == v) a = u + v - a; if (b == u or b == v) b = u + v - b; } }; auto merge = [&](int u, int v) { for (auto& [a, b] : uv) { // 把所有 u 换成 v if (a == u) a = v; if (b == u) b = v; } };
vector<int> deg(N); for (auto& [u, v] : uv) { deg[u]++; deg[v]++; } ch(min_element(begin(deg), end(deg)) - begin(deg), N - 1); // 交换 度最小的点 和 最后的点 int mindeg = *min_element(begin(deg), end(deg)); if (mindeg > 3) returncalc1(N, K, uv); // 所有度都 > 3
vector<int> adj; rep(_,0,mindeg) rep(j,0,size(uv)) { // 每次找到和 最后点(N-1) 相连的一条边删除 auto [u,v] = uv[j]; if (u == N-1or v == N-1) { adj.push_back(u+v-(N-1)); // 相连的另外一个点 uv.erase(begin(uv) + j); break; } } sort(begin(adj), end(adj)); // 和最小度的点相邻点 rep(i,0,size(adj)) ch(adj[size(adj)-1-i],N-2-i); // 和最小度的点相邻点换到末尾(注意顺序是必要的 mint ans = calc(N - 1, K, uv) * (K - mindeg); // 0,1,2,3 时 不选所有边的情况 if (mindeg == 2) { merge(N-2,N-3); ans += calc(N - 2, K, uv); // 把和u相连的点合并成一个点(N-3), 移除u和被合并的 } elseif (mindeg == 3) { rep(_,0,3){ // 选两个边 auto old = uv; // backup merge(N-2,N-3); // 每次 合并两个 ans += calc(N - 2, K, uv); uv = old; // load backup ch(N - 3, N - 4); // 轮换 N-2,N-3,N-4 ch(N - 2, N - 3); } merge(N-2,N-4); merge(N-3,N-4); ans -= calc(N - 3, K, uv); } return ans; } intmain(){ int N=read(); int M=read(); int K=read(); vector<pair<int, int>> uv; rep(i,0,M) uv.push_back({read()-1,read()-1}); printf("%d\n", calc(N, K, uv).val()); }