From 5e77358d929a83b34373b5b9784e0fadd9cda579 Mon Sep 17 00:00:00 2001 From: Zengtudor Date: Sun, 24 Nov 2024 16:55:05 +0800 Subject: [PATCH] update --- src/11/P9869/P9869.cpp | 3 ++ src/11/P9869/P9869.md | 81 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 src/11/P9869/P9869.cpp create mode 100644 src/11/P9869/P9869.md diff --git a/src/11/P9869/P9869.cpp b/src/11/P9869/P9869.cpp new file mode 100644 index 0000000..294989d --- /dev/null +++ b/src/11/P9869/P9869.cpp @@ -0,0 +1,3 @@ +int main(){ + +} \ No newline at end of file diff --git a/src/11/P9869/P9869.md b/src/11/P9869/P9869.md new file mode 100644 index 0000000..e2b3801 --- /dev/null +++ b/src/11/P9869/P9869.md @@ -0,0 +1,81 @@ +这个问题涉及三值逻辑(True、False、Unknown)变量的赋值与操作,需要找到一种初始赋值方案,使得在执行所有操作后,每个变量的最终值与初始值相同,并且使初始赋值中 `Unknown` 的变量尽可能少。 + +### 问题分析 + +1. **变量与操作**: + - 有 `n` 个变量,每个变量的值可以是 `T`、`F` 或 `U`。 + - 有 `m` 条操作,这些操作包括直接赋值(如 `x_i ← T`)、赋值为另一个变量的值(如 `x_i ← x_j`)、或赋值为另一个变量的逻辑非(如 `x_i ← ¬x_j`)。 + +2. **目标**: + - 执行所有操作后,所有变量的最终值与初始值相同。 + - 在满足上述条件的前提下,初始赋值中 `Unknown` 的变量数最少。 + +### 思路概述 + +为了满足最终值等于初始值,需要建立变量之间的依赖关系,并找出这些关系中的约束条件。可以将变量及其值的赋值关系看作是一个等式系统,通过这些等式来确定变量的可能取值。为了有效管理这些等式并高效求解,使用 **并查集(Union-Find** 是一种常见的方法。 + +### 具体步骤 + +1. **表示三值逻辑**: + - 将 `T`、`F`、`U` 分别映射为不同的整数值,便于在代码中处理: + - `T` 被表示为 `100001` + - `F` 被表示为 `-100001` + - `U` 被表示为 `0` + +2. **并查集初始化**: + - 使用一个数组 `fa` 来表示每个变量的父节点或代表元素。初始时,每个变量的父节点指向自己。 + +3. **处理每条操作**: + - **直接赋值操作**(`T`、`F`、`U`): + - 如果操作是 `x_i ← T`,则将 `fa[x_i]` 设为 `T` 的表示值。 + - 类似地处理 `x_i ← F` 和 `x_i ← U`。 + - **赋值为另一个变量的值**(`+` 操作): + - 如果操作是 `x_i ← x_j`,则将 `fa[x_i]` 设为 `fa[x_j]`,表示 `x_i` 与 `x_j` 的值相同。 + - **赋值为另一个变量的非值**(`-` 操作): + - 如果操作是 `x_i ← ¬x_j`,则将 `fa[x_i]` 设为 `-fa[x_j]`,表示 `x_i` 是 `x_j` 值的逻辑非。 + +4. **查找变量的最终值**: + - 使用 `find` 函数来查找变量的代表值。 + - 在 `find` 函数中: + - 对于 `T` 和 `F`,直接返回其表示值。 + - 对于 `U`,返回 `0`。 + - 对于其他情况,通过递归查找父节点,处理逻辑非的情况,并使用 `book` 数组避免死循环。 + +5. **计算 `Unknown` 的最小数量**: + - 遍历所有变量,使用 `find` 函数确定每个变量的最终值。 + - 如果某个变量的最终值为 `U`,则计数。 + - 输出所有测试数据中 `Unknown` 变量的最小数量。 + +### 关键细节与优化 + +- **处理逻辑非(`¬`)**: + - 逻辑非会改变变量的值,因此在并查集中需要表示变量与其非值的关系。 + - 使用负值表示逻辑非关系,例如 `x_i ← ¬x_j` 表示 `fa[x_i] = -fa[x_j]`。 + +- **防止死循环**: + - 当变量的代表值可能因逻辑非关系而相互指向时,可能会引发无限递归。通过 `book` 数组记录已经访问过的节点,从而避免死循环。 + +- **高效的查找操作**: + - 使用路径压缩技术优化 `find` 函数,使得查找操作的时间复杂度接近常数时间,确保算法在大规模数据(`n, m ≤ 10^5`)下依然高效。 + +### 示例解析 + +以第一个样例为例: + +``` +3 3 +- 2 1 +- 3 2 ++ 1 3 +``` + +- 操作步骤: + 1. `x_2 ← ¬x_1`:`fa[2] = -fa[1]` + 2. `x_3 ← ¬x_2`:`fa[3] = -fa[2]` + 3. `x_1 ← x_3`:`fa[1] = fa[3]` + +- 通过并查集的合并与查找,最终确定每个变量的值,使得初始值与最终值相同,并且 `Unknown` 的数量最少。在该示例中,可以赋予 `x1 = T`,`x2 = F`,`x3 = T`,使得 `Unknown` 的数量为 `0`。 + +### 总结 + +该解决方案通过并查集有效地管理变量之间的赋值与逻辑关系,处理了直接赋值、变量赋值以及逻辑非赋值的情况。通过高效的查找与合并操作,能够在大规模数据下快速求解,同时通过合理的表示与优化,确保了算法的正确性与效率。 \ No newline at end of file