当前位置: 首页 > news >正文

洛谷P9869 [NOIP2023] 三值逻辑 题解

由于全是赋值操作,我们容易发现每个值最终状态所依赖的都是某个确定的状态(\(T\)\(F\)\(U\)),或者是某个位置的初始值。于是先 \(O(m)\) 预处理每个 \(x_i\) 的最终状态来源 \(p_i\),即 \(x_i\) 的值依赖于 \(x_{p_i}\),以及它们的关系 \(r_i\)\(0\) 表示相等,\(1\) 表示取反。

考虑图论建模,无向边 \((i,p_i)\) 表示 \(i\)\(p_i\) 是取反的关系。

如果 \(r_i=0\) 就并查集缩这两个点(为了保持图中的边全是取反意义),取反则连无向边。特别的,如果 \(i\) 的值依赖一个确定的值,建三个特殊点 \(T\)\(F\)\(U\) 连单向边向 \(i\),表示支配关系,答案计入 \(U\) 支配的联通块中点数,和不被任何一个特殊点支配的、且存在奇环的联通块中的点数。

可能的疑问

  1. 为什么是奇环?

若联通块中存在奇环,根据我们这个图的边的定义,它一定会得出自己是自己的取反这种显然错误的结论。

  1. 为什么不用管 \(T\)\(F\) 中的联通块?

联通块里所有的点的状态都会被他们的源点——特殊点所确定,题目保证方案存在,所以不用管这里是不是有冲突。

code

#include <bits/stdc++.h>
#define int int64_t
//#define int __int128
//#define MOD (1000000007)
//#define eps (1e-6)
#define endl '\n'
#define debug_endl cout<<endl;
#define debug cout<<"debug"<<endl;
using namespace std;
const int MAXN=1e5+10;
int c,t,n,m,ans;
int p[MAXN],r[MAXN];
int fa[MAXN];
set<int> g[MAXN];
bool vised[MAXN];
int dep[MAXN],cnt[MAXN];
inline int find(int x){if(fa[x]==x){return x;}return fa[x]=find(fa[x]);
}
void merge(int x,int y){int fx=find(x);int fy=find(y);if(fx!=fy){fa[fy]=fx;cnt[fx]+=cnt[fy];}
}
pair<int,int> dfs(int x){pair<int,int> res(0,cnt[x]);vised[x]=true;for(int v:g[x]){if(vised[v]){if(((dep[x]-dep[v])&1)==0){res.first=1;}}else{dep[v]=dep[x]+1;auto [f,w]=dfs(v);res.first|=f;res.second+=w;}}return res;
}
signed main(){//freopen("P9869_3.in","r",stdin);//freopen(".out","w",stdout);ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);cin>>c>>t;while(t--){cin>>n>>m;ans=0;for(int i=1;i<=n+3;++i){p[i]=i;r[i]=0;fa[i]=i;vised[i]=false;cnt[i]=1;g[i].clear();dep[i]=0;}for(int i=1;i<=m;++i){char c;int u,v;cin>>c;if(c=='-'){cin>>u>>v;p[u]=p[v];r[u]=r[v]^1;}else if(c=='+'){cin>>u>>v;p[u]=p[v];r[u]=r[v];}else if(c=='T'){cin>>u;p[u]=n+1;r[u]=0;}else  if(c=='F'){cin>>u;p[u]=n+2;r[u]=0;}else{cin>>u;p[u]=n+3;r[u]=0;}}for(int i=1;i<=n;++i){if(!r[i]&&p[i]<=n){merge(i,p[i]);}}for(int i=1;i<=n;++i){if(p[i]>n){g[p[i]].emplace(find(i));continue;}if(r[i]){g[find(i)].emplace(find(p[i]));g[find(p[i])].emplace(find(i));}}ans+=dfs(n+3).second-1;dfs(n+2);dfs(n+1);for(int i=1;i<=n;++i){if(vised[find(i)]) continue;auto [f,w]=dfs(find(i));ans+=f*w;}cout<<ans<<endl;}return 0;
}
http://www.jsqmd.com/news/323157/

相关文章:

  • 一、C++简介与环境配置
  • 【游戏推荐】NBA 2K 欢乐竞技场2 (NBA 2K Playgrounds 2)免安装中文版
  • 金融领域元学习在模型快速适应中的应用
  • 模板元编程调试方法
  • 基于单片机的无线病床呼叫系统设计
  • Python日志记录(Logging)最佳实践
  • 大语言模型微调数据对齐五大核心算法SFT、RLHF、DPO、PPO、GRPO
  • AI Agent在预测分析中的应用
  • 2026年AIR SCI1区TOP,基于三维 Rényi 熵模型的多特征融合与量子混合算法+阿尔茨海默病脑图像分割,深度解析+性能实测
  • C++中的适配器模式变体
  • 5种落地性最强的对齐微调数据集格式
  • GPU thread 概念
  • 大数据清洗:提高数据质量的10个实用技巧
  • 使用XGBoost赢得Kaggle比赛
  • 3年后端老兵亲述大模型转型血泪史:后端开发转行大模型应用开发(附完整大模型学习路线)
  • 深度解析!提示工程行业标准的优化策略
  • 基于深度学习的水下鱼类识别系统(YOLOv8+YOLO数据集+UI界面+Python项目+模型)
  • 评论盖楼系统最优解:扁平化高并发+无限层级通用
  • 轻松处理旧坚果二手投影仪:专业回收,快速变现
  • 【文化课】2025~2026 学年第一学期 期末考试 总结
  • Python GUI开发:Tkinter入门教程
  • 怎么在线编辑修改查看glb/gltf格式模型,支持多选,反选择多物体,单独导出物体(免费)
  • 詹姆斯·蒙蒂尔的市场异常现象研究
  • 梦断代码阅读笔记2
  • 西门子 S7-1200 通过 TIA Portal 实现对 MINAS A6 伺服的控制
  • Exce校验并导入(上传OSS)
  • POE 延长器突破标准以太网限制,延长网络设备的部署范围
  • 学习的门道和思路
  • 一个网关盒子,打通 Profinet 与 CAN 的通信壁垒
  • 单元测试在C++项目中的实践