CF 1310D Tourism 题解

Link

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})\)

考虑计算单次染色成功概率:

  1. \(v_0\) 颜色任意,成功概率 \(1\)
  2. \(v_1\) 颜色必须异于 \(v_0\),成功概率 \(\frac{1}{2}\)
  3. \(v_2\) 颜色必须异于 \(v_1\),成功概率 \(\frac{1}{2}\)
  4. \(\dots\)
  5. \(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;
}
posted @ 2025-11-06 10:37  夢回路  阅读(6)  评论(0)    收藏  举报