ARC093E Bichrome Spanning Tree
题意
- 给定一张 个点 条边的无重边无自环的无向图,边有边权。
- 求给边染黑白两色,使得包含两种颜色的边的边权和最小的生成树的边权和恰好为 的方案数。
- ,,答案对 取模。
题解
首先求出 MST 的边权和 。
如果 显然无解,以下不考虑这种情况。
显然最终的包含两种颜色的边的边权和最小的生成树要么就是 MST(要求 ,方案数为 ),要么 MST 里的边全都是同一种颜色,然后找到一条与这种颜色不同的边 ,用这条边替换 MST 中 之间的最大边权,使得替换后的边权和最小。
因此我们要求出有多少条边替换后会使边权和 ,设个数分别为 ,则这种情况的方案数为 。
设 同阶,总时间复杂度可以做到 ,但本题 即可通过。
代码
const int N = 1e3 + 7, inf = 1 << 30;
int n, m, a[N][N], d[N], f[N];
bool v[N], u[N][N];
ll X, W;
vi e[N];
modint ans;
inline void prim() {
for (int i = 0; i <= n; i++) d[i] = inf;
d[1] = 0;
for (int i = 1; i <= n; i++) {
int x = 0;
for (int j = 1; j <= n; j++)
if (!v[j] && d[j] < d[x]) x = j;
v[x] = 1, W += d[x];
if (f[x])
e[x].pb(f[x]), e[f[x]].pb(x),
u[x][f[x]] = u[f[x]][x] = 1;
for (int y = 1; y <= n; y++)
if (!v[y] && d[y] > a[x][y])
d[y] = a[x][y], f[y] = x;
}
}
int dfs(int x, int f, int z) {
for (int y : e[x])
if (y != f) {
if (y == z) return a[x][y];
int ret = dfs(y, x, z);
if (ret) return max(ret, a[x][y]);
}
return 0;
}
int main() {
rd(n, m), rd(X);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
a[i][j] = inf;
for (int i = 1; i <= n; i++) a[i][i] = 0;
for (int i = 1, x, y, z; i <= m; i++)
rd(x, y, z), a[x][y] = a[y][x] = min(a[x][y], z);
prim();
if (W > X) return print(0), 0;
if (W == X) ans = ((modint)2 ^ m) - ((modint)2 ^ (m - n + 2));
int b = 0, c = 0;
for (int i = 1; i <= n; i++)
for (int j = i + 1; j <= n; j++)
if (a[i][j] < inf && !u[i][j]) {
ll K = W + a[i][j] - dfs(i, 0, j);
if (K == X) ++b;
if (K > X) ++c;
}
ans += ((modint)2 ^ (b + c + 1)) - ((modint)2 ^ (c + 1));
print(ans);
return 0;
}
评论
暂无已公开评论。