[题解] AT_abc386_g [ABC386G] Many MST
posted on 2024-12-30 11:11:16 | under | source
题意:为完全图的每条边赋值 \([1,m]\),求所有情况下 MST 权值之和。
不妨认为权值为 \([0,m)\),最后再加回去即可。
无从下手,需要做一步转化:考虑 kruskal 的过程,依次将权值为 \(0\dots m-1\) 的边加入。不妨记 \(G_k\) 为将 \(<k\) 的边全部加入后得到的图,\(c(G_k)\) 为 \(G_k\) 的连通分量集合。那么 \(n-|c(G_k)|\) 等于 MST 上权值 \(< k\) 的边数量,所以有:
对于 \(-m\),总的贡献是 \(-m^{\frac {n(n-1)}2+1}\)。而 \(|c(G_k)|\) 等价于求满足条件的连通分量数量,枚举 \(k\),枚举连通分量 \(T\),记 \(V,E\) 为 \(T\) 的点数和边数,那么使它在 \(k\) 时产生贡献的赋值方案数为:
含义是:内部边 \(< k\),外部边随意,对于连接内外部或在内部但不在连通分量内的边,取值 \(\ge k\)。
不妨枚举 \(V=s\),那么 \(k\) 的总贡献就是:
提取公因式:
并不关心点的编号,所以记 \(f(s)\) 为连通分量大小为 \(s\) 时,后面那串式子的值,代入:
求出 \(f\) 即可。对于连通分量一类的计数问题,可以借鉴 ABC213G 的做法,即总价值减去不连通情况的价值。先看看总价值 \(W\):
然后是不连通的价值 \(W_2\)。不连通可以看做:\(1\) 所在连通分量、其它点随意组合(这个刚刚解决了)。单独计算两部分的价值都是容易的,将其乘起来后,发现只需修正 \((m-k)^{\frac{s(s-1)}2}\) 这部分即可:
最后 \(f_s=W-W_2\)。
完结撒花,复杂度 \(O(n^2m)\)。
代码
注意常数优化。
#include<bits/stdc++.h>
#pragma GCC optimize(3, "Ofast", "inline")
using namespace std;
#define ADD(a, b) a = (a + b) % mod
const int N = 5e2 + 5, mod = 998244353;
int n, m, ans, f[N], jc[N], jcinv[N];
int qstp[N][N * N], C[N][N];
inline void solve(int k){
for(int s = 1; s <= n; ++s){
f[s] = qstp[m][s * (s - 1) / 2];
for(int i = 1; i < s; ++i)
ADD(f[s], 1ll * (mod - 1) * f[i] % mod * C[s - 1][i - 1] % mod * qstp[m][(s - i) * (s - i - 1) / 2] % mod * qstp[m - k][i * (s - i)] % mod);
ans = (ans + 1ll * qstp[m][(n - s) * (n - s - 1) / 2] * qstp[m - k][s * (n - s)] % mod * C[n][s] % mod * f[s] % mod) % mod;
}
}
signed main(){
for(int i = 0; i < N; ++i){
qstp[i][0] = 1, C[i][0] = C[i][i] = 1;
for(int j = 1; j < N * N; ++j) qstp[i][j] = 1ll * qstp[i][j - 1] * i % mod;
for(int j = 1; j < i; ++j) C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % mod;
}
cin >> n >> m;
ans = (1ll * (n - 1) * qstp[m][n * (n - 1) / 2] % mod + 1ll * (mod - 1) * qstp[m][n * (n - 1) / 2 + 1] % mod) % mod;
for(int i = 1; i <= m; ++i) solve(i);
cout << ans;
return 0;
}

浙公网安备 33010602011771号