CF 1310D Tourism 题解
Queueforces.
随机化。一个关键的观察是 \(k \leq 10\),意味着有效路径上最多只有 \(10\) 个,同时根据二分图的性质,题目中要求了图中没有奇环,说明图是一张二分图。
暴力去跑边的复杂度是天文级别的 \(O(n^k)\)。回到问题本身,要求我们在图中找到找到一条从 \(1\) 出发,经过恰好 \(k\) 步后回到 \(1\) 的最短路径,同时这个不能是奇环。通过对二分图上节点进行随机染色,我们每次钦定路径必须在两种颜色之间交替,保证最终的环为偶。知道了路径转移,考虑 DP 计算最小代价。记 \(f_{i, j}\) 为经过 \(i\) 条路径,到达节点 \(j\) 的最小代价,转移:
\[f_{i + 1, v} = \min(f_{i + 1, v}, f_{i, u} + dis(u, v))
\]
随机化正确性不太会证啊,对于最优路径上的 \(k + 1\) 个节点,要求:
- \(color(v_0) = color(v_k)\)
- \(color(v_i) \neq color(v_{i + 1})\)
考虑计算单次染色成功概率:
- \(v_0\) 颜色任意,成功概率 \(1\)
- \(v_1\) 颜色必须异于 \(v_0\),成功概率 \(\frac{1}{2}\)
- \(v_2\) 颜色必须异于 \(v_1\),成功概率 \(\frac{1}{2}\)
- \(\dots\)
- \(v_k\) 颜色必须异于 \(v_{k - 1}\),且必须等于 \(v_0\) 颜色。由于 \(k\) 是偶数,经过 \(k\) 次变换之后 \(v_0\) 的颜色必定等于 \(v_k\) 的颜色
所以,单次成功概率为:
\[Pr = 1 \times \Pi_{k - 1} \frac{1}{2} = (\frac{1}{2})^{k - 1}
\]
当 \(k = 10\) 时:
\[Pr = (\frac{1}{2})^{9} = \frac{1}{512}
\]
假设进行 \(5000\) 次染色,单次失败概率:
\[Pr' = 1 - Pr = \frac{511}{512}
\]
所有染色均失败概率:
\[Pr'' = (Pr')^{5000}
\]
成功概率:
\[Pr''' = 1 - Pr'' \approx 99.9943\%
\]
当然也可以卡时。
#include <bits/stdc++.h>
using i64 = long long;
using f64 = double;
constexpr int N = 107;
constexpr int K = 20;
constexpr f64 MXT = 2;
constexpr i64 inf = std::numeric_limits<i64>::max();
int n, k;
i64 ans;
int c[N];
i64 f[K][N], d[N][N];
std::random_device rdv;
std::mt19937 myrand(rdv());
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cin >> n >> k;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++)
std::cin >> d[i][j];
}
ans = inf;
while (clock() / CLOCKS_PER_SEC < MXT) {
for (int i = 1; i <= n; i++) {
c[i] = myrand() & 1;
}
memset(f, 0x7f, sizeof(f));
f[0][1] = 0;
for (int i = 0; i < k; i++) {
for (int u = 1; u <= n; u++) {
for (int v = 1; v <= n; v++)
if (c[u] != c[v])
f[i + 1][v] = std::min(f[i + 1][v], f[i][u] + d[u][v]);
}
}
ans = std::min(ans, f[k][1]);
}
std::cout << ans << "\n";
return 0;
}

浙公网安备 33010602011771号