mirror of
https://gitcode.com/Zengtudor/alg2025.git
synced 2025-10-28 02:52:41 +00:00
feat: 添加三值逻辑问题解决方案及测试代码
实现P9869问题的解决方案,包含主逻辑处理文件和测试文件。主文件处理三值逻辑(T/F/U)的变量赋值和关系操作,测试文件提供更详细的实现和注释。添加路径压缩和环检测机制来正确处理逻辑依赖关系。
This commit is contained in:
parent
5df5ae14a2
commit
413d070dbb
76
src/10/25/P9869.cpp
Normal file
76
src/10/25/P9869.cpp
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#include <bitset>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <iostream>
|
||||||
|
using ll = int64_t;
|
||||||
|
|
||||||
|
const ll maxn = 1e5+5;
|
||||||
|
const ll T=1e5+3,F=-1e5-3,U=0;
|
||||||
|
ll c,t,n,m,f[maxn];
|
||||||
|
std::bitset<2*maxn> vis;
|
||||||
|
#define vis(x)vis[(x)+n]
|
||||||
|
|
||||||
|
static inline ll find(ll x){
|
||||||
|
ll ret;
|
||||||
|
if(x==T||x==F)ret=x;
|
||||||
|
else if(vis(-x)||x==U){
|
||||||
|
ret=U;
|
||||||
|
}else if(vis(x))ret=T;
|
||||||
|
else if(x<0){
|
||||||
|
if(-f[-x] == x)ret=x;
|
||||||
|
else{
|
||||||
|
vis(x)=true;
|
||||||
|
f[-x]=ret=find(-f[-x]);
|
||||||
|
vis(x)=false;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if(f[x]==x)ret=x;
|
||||||
|
else{
|
||||||
|
vis(x)=true;
|
||||||
|
f[x]=ret=find(f[x]);
|
||||||
|
vis(x)=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void solve(){
|
||||||
|
vis.reset();
|
||||||
|
std::cin>>n>>m;
|
||||||
|
ll ans=0;
|
||||||
|
for(ll i=1;i<=n;i++)f[i]=i;
|
||||||
|
for(ll i=1;i<=m;i++){
|
||||||
|
char c;
|
||||||
|
std::cin>>c;
|
||||||
|
if(c=='T' || c=='F' || c=='U'){
|
||||||
|
ll v;
|
||||||
|
std::cin>>v;
|
||||||
|
switch (c) {
|
||||||
|
case 'T':f[v]=T;break;
|
||||||
|
case 'F':f[v]=F;break;
|
||||||
|
case 'U':f[v]=U;break;
|
||||||
|
}
|
||||||
|
}else if(c=='+'){
|
||||||
|
ll i,j;
|
||||||
|
std::cin>>i>>j;
|
||||||
|
f[i]=f[j];
|
||||||
|
}else if(c=='-'){
|
||||||
|
ll i,j;
|
||||||
|
std::cin>>i>>j;
|
||||||
|
f[i]=-f[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(ll i=1;i<=n;i++){
|
||||||
|
ans+=find(i)==U;
|
||||||
|
}
|
||||||
|
std::cout<<ans<<"\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(){
|
||||||
|
std::iostream::sync_with_stdio(false);
|
||||||
|
std::cin.tie(nullptr);
|
||||||
|
|
||||||
|
std::cin>>c>>t;
|
||||||
|
while (t--) {
|
||||||
|
solve();
|
||||||
|
}
|
||||||
|
}
|
||||||
97
src/10/25/P9869t.cpp
Normal file
97
src/10/25/P9869t.cpp
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
#include<bits/stdc++.h>
|
||||||
|
#define int long long
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
// 定义三个特殊值来表示三值逻辑
|
||||||
|
// 使用很大的数字来避免与普通变量下标冲突
|
||||||
|
const int T = 100001, F = -100001, U = 0; // T代表True,F代表False,U代表Unknown
|
||||||
|
|
||||||
|
int c, t, n, m, a, b, fa[100005]; // fa数组用于记录每个变量的当前值或依赖关系
|
||||||
|
char ch[100005]; // 存储每条语句的操作类型
|
||||||
|
bool book[300005]; // 标记数组,用于在递归查找时检测环
|
||||||
|
|
||||||
|
// 核心函数:查找变量x的最终逻辑值
|
||||||
|
int find(int x) {
|
||||||
|
int re; // 返回值
|
||||||
|
|
||||||
|
// 情况1:如果x已经是基础值(T/F/U),直接返回
|
||||||
|
if (x == T || x == F) re = x;
|
||||||
|
else if (book[n - x] || x == U) re = U;
|
||||||
|
// 这里book[n-x]是处理负数的标记,x==U表示已经是Unknown
|
||||||
|
|
||||||
|
// 情况2:如果x被标记为True(在递归路径中)
|
||||||
|
else if (book[x + n]) re = T;
|
||||||
|
|
||||||
|
// 情况3:处理负数(表示逻辑非操作的结果)
|
||||||
|
else if (x < 0) {
|
||||||
|
// 如果负数指向自己,说明形成了自环,保持原值
|
||||||
|
if (x == -fa[-x]) re = x;
|
||||||
|
else {
|
||||||
|
book[x + n] = 1; // 标记当前节点,防止无限递归
|
||||||
|
// 递归查找:¬(¬A) = A,所以这里取双重否定
|
||||||
|
re = find(-fa[-x]);
|
||||||
|
book[x + n] = 0; // 回溯,清空标记
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 情况4:处理正数(普通变量引用)
|
||||||
|
else {
|
||||||
|
// 如果指向自己,说明是基础值或已确定的值
|
||||||
|
if (x == fa[x]) re = x;
|
||||||
|
else {
|
||||||
|
book[x + n] = 1; // 标记当前节点
|
||||||
|
// 递归查找依赖的值
|
||||||
|
re = fa[x] = find(fa[x]); // 路径压缩
|
||||||
|
book[x + n] = 0; // 回溯,清空标记
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return re;
|
||||||
|
}
|
||||||
|
|
||||||
|
signed main() {
|
||||||
|
cin >> c >> t; // 读入测试点编号和数据组数
|
||||||
|
|
||||||
|
while (t--) {
|
||||||
|
cin >> n >> m; // 变量个数和语句条数
|
||||||
|
|
||||||
|
// 初始化:每个变量最初指向自己
|
||||||
|
for (int i = 1; i <= n; i++) fa[i] = i;
|
||||||
|
|
||||||
|
// 处理每条语句
|
||||||
|
for (int i = 1; i <= m; i++) {
|
||||||
|
cin >> ch[i]; // 读入操作类型
|
||||||
|
|
||||||
|
if (ch[i] == 'T') { // 赋值为True
|
||||||
|
cin >> a;
|
||||||
|
fa[a] = T; // 直接标记为T
|
||||||
|
}
|
||||||
|
else if (ch[i] == 'F') { // 赋值为False
|
||||||
|
cin >> a;
|
||||||
|
fa[a] = F; // 直接标记为F
|
||||||
|
}
|
||||||
|
else if (ch[i] == 'U') { // 赋值为Unknown
|
||||||
|
cin >> a;
|
||||||
|
fa[a] = U; // 直接标记为U
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cin >> a >> b;
|
||||||
|
if (ch[i] == '+') { // 赋值操作:x_a ← x_b
|
||||||
|
fa[a] = fa[b]; // 直接复制值或引用
|
||||||
|
}
|
||||||
|
else { // 取反操作:x_a ← ¬x_b
|
||||||
|
fa[a] = -fa[b]; // 用负数表示逻辑非
|
||||||
|
// 例如:如果fa[b]=T(100001),那么fa[a]=-100001
|
||||||
|
// 这表示"非True",在find函数中会特殊处理
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ans = 0;
|
||||||
|
// 统计最终值为Unknown的变量个数
|
||||||
|
for (int i = 1; i <= n; i++) {
|
||||||
|
if (find(i) == U) ans++;
|
||||||
|
}
|
||||||
|
cout << ans << endl;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user