Luogu P9869 NOIp2023 三值逻辑 题解 [ 绿 ] [ 带权并查集 ]

news/2024/11/19 22:19:35/文章来源:https://www.cnblogs.com/zhr0102/p/18555719

三值逻辑:有点坑并且细节较繁琐,但有点板子的并查集。

修改操作

发现对于每个点,只有对他的最后一次操作才是有用的,所以记录下最终的祖先即可。

然而这里并不能用并查集来实现,因为并查集它具有的是传递性,无论你路不路径压缩,每次修改一个父节点时它的子节点一定会被修改,所以我们不能使用并查集。

但是可以使用并查集相关思想。

首先我们建立虚拟源点 \(n+1\) 表示 \(T\)\(n+2\) 表示 \(U\)。到某个点的距离为奇数时表示与这个点的值相反,为偶数则表示与这个点的值相等。

每次修改后,我们都直接指向父节点的祖先节点。为啥祖先节点就可以呢?因为此时祖先节点是未被修改的,而根据题目中“使得每个变量初始值与最终值相同”,所以这里跟祖先节点连边相当于和祖先节点的初值连边。自然是正确的了。

upd:这里其实可以用并查集,但是要时时刻刻路径压缩,每 combine 一次就要压一次。

判断合法性

对于直接连向 \(U\) 的连通块,最终的结果一定是 \(U\)

其余如果出现矛盾的连通块,最终的结果也一定全部是 \(U\)。这个的实现,只需要每次合并的时候判断一下到祖先节点的距离就好了。

时间复杂度 \(O(tn)\)

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define lc (p<<1)
#define rc ((p<<1)|1)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pi;
int n,m,tof[100005],tod[100005],f[100005],d[100005];
//n+1: T ,n+2: U
bitset<100005>ilg;
int findf(int x)
{if(f[x]!=x){int orif=f[x];f[x]=findf(f[x]);d[x]=(d[orif]^d[x]);}return f[x];
}
void combine(int x,int y,int td)
{int fx=findf(x),fy=findf(y);if(fx!=fy){d[fx]=(d[y]^td^d[x]);f[fx]=fy;}
}
void init()
{for(int i=1;i<=n+2;i++)f[i]=i,d[i]=0;
}
void solve()
{cin>>n>>m;for(int i=1;i<=n+2;i++){tof[i]=i;tod[i]=0;}ilg.reset();for(int i=1;i<=m;i++){int a,b;char v;cin>>v>>a;if(v=='+'){cin>>b;tof[a]=tof[b];tod[a]=tod[b];}else if(v=='-'){cin>>b;tof[a]=tof[b];tod[a]=(tod[b]^1);            }else if(v=='T'){tof[a]=n+1;tod[a]=0;}else if(v=='F'){tof[a]=n+1;tod[a]=1;            }else{tof[a]=n+2;tod[a]=0;}}init();for(int i=1;i<=n;i++){if(findf(i)==findf(tof[i])){if(tod[i]!=(d[i]^d[tof[i]]))ilg[findf(i)]=1;}combine(i,tof[i],tod[i]);}int ans=0;for(int i=1;i<=n;i++)if(findf(i)==n+2||ilg[findf(i)])ans++;cout<<ans<<'\n';
}
int main()
{//freopen("tribool.in","r",stdin);//freopen("tribool.out","w",stdout);ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int x,t;cin>>x>>t;while(t--)solve();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/837032.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网卡-国家码

交互大屏、笔记本等产品出口海外,也是网络相关设备,会发出AP热点网络,所以出口海外要符合当地法规。 大屏需要以自带网卡开出本地热点,用于投屏、设备间协同等操作。热点这块受限影响的是信道,每个国家都有雷达信道以及其它军事等受限信道,使用信道时避开这些雷达信道。…

人工智能之机器学习基础——K-Means

K-Means 是一种无监督学习算法,用于将数据划分为 KKK 个簇(Clusters),使得每个簇中的样本尽可能接近其簇中心,簇之间尽可能远离。K-Means 常用于聚类分析,例如客户分群、图像分割等任务。

2643: 鼠鼠的薪水 while

include <bits/stdc++.h> using namespace std; int maxx, a, b, c; int main( ) { cin >> a; b=10; c=3; while(b!=a) { if (c1||c2) { b+=7; } b--; c++; c%=7; maxx++; } cout << maxx; } 反思: while(b<a) 做错,正确为: while(b!=a)

人工智能之机器学习基础——决策树(Decision Tree)

决策树是一种用于分类和回归的非参数模型,能够通过一系列的条件判断(分裂规则)将输入数据划分为子区域,从而完成预测任务。 1. 决策树的基本结构 决策树由以下三部分组成:根节点(Root Node):表示整个数据集,最初没有任何划分。内部节点(Internal Node):表示一个特定…

Vue UI创建项目问题

1.使用cmd命令行【Vue UI】创建项目出现【 Failed to get response from https://registry.npm.taobao.org/vue-cli-version-marker】 原因:镜像问题 处理:npm config get registry查看镜像源是【https://registry.npm.taobao.org/】 替换镜像源:(换成TX的,TaoBao的创建项…

基于Java+Springboot+Jpa+Mysql实现的在线网盘文件分享系统功能设计与实现二

今天发布的是一款由springboot+freemark+jpa+MySQL实现的在线网盘文件分享系统,其功能跟百度网盘非常类似,普通用户可以注册登录,注册后默认分配1G的空间大小,登录进去后可以新建文件夹、上传各种类型的文件、文件移动、复制、下载、删除、分享,分享分为私密分享和公开分享…

『模拟赛』多校A层冲刺NOIP2024模拟赛24

『模拟赛记录』多校A层冲刺NOIP2024模拟赛24Rank 。A. 选取字符串 签。 一眼想到动物园那个题面,kmp 求出的 next 数组实际上就是既是它的后缀又是它的前缀的字符串中(它本身除外),最长的长度。 那么可以想到,某个串除了它自身外,能选的 p/q 最长即为它的 next。更短的可…

osg三维场景中拾取鼠标在模型表面的点击点

osg三维场景中拾取鼠标在模型表面的点击点#include <osg/Group> #include <osg/Geode> #include <osg/ShapeDrawable> #include <osgDB/ReadFile> #include <osgViewer/Viewer> #include <osgGA/GUIEventHandler> #include <osgGA/Trac…

流和向量(Streams and Vectors)

在GNU Radio的官方教程中,提到了两个重要的块连接方式:流和向量(Streams and Vectors)。具体的章节链接为: 🔗:流和向量 - GNU Radio 🔗:带有向量的 Python 块 - GNU Radio 官方文档对流和向量的概念和使用有着简介和直观的讲述,但对于两者之间的转化方法以及何时使…