P9869-NOIP2023-B-三值逻辑
题目传送门
题外话
由于很多人对本题并查集做法提问,本人于二零二四年一月二十日对此篇题解进行了更新。
巧妙方法
相信大家已经知道此题的并查集、高斯消元等解法了,本人在此篇题解对此不再赘述,只是给大家提供一种代码细节——处理三值逻辑的符号的一些巧妙的方法。
我们其实可以把三值逻辑分别赋予三个值,再把这三个值赋予三个常量,常量名就以
本人做法
这里具体说一下并查集做法(也是更新部分)。
我们的大体思路是先按照题意模拟,给所有输入的操作的相关变量用并查集标记,在并查集查询操作前我们就可以确定哪些变量的值是确定的,哪些是不确定的,这时我们的任务就是最小化不确定的变量中
我们把这两种情况查询出来,再统计个数,就是最终答案了!由于 别问我怎么知道的,哭)。
由于我们要查询的
然后,就没有然后了(写代码呗)。
代码
上代码(马蜂良好,条件语句清楚,适宜阅读)。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int T=100001,F=-100001,U=0;//三值逻辑
int c,t,n,m,a,b,fa[100005];
char ch[100005];
bool book[300005];
int find(int x) {
int re;
if(x==T||x==F)re=x;
else if(book[n-x]||x==U)re=U;
else if(book[x+n])re=T;
else if(x<0) {
if(x==-fa[-x])re=x;
else {
book[x+n]=1;
re=find(-fa[-x]);//这里注意细节
book[x+n]=0;//清空
}
} 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') {
cin>>a;
fa[a]=T;
} else if(ch[i]=='F') {
cin>>a;
fa[a]=F;
} else if(ch[i]=='U') {
cin>>a;
fa[a]=U;
} else {
cin>>a>>b;
if(ch[i]=='+')fa[a]=fa[b];
else fa[a]=-fa[b];
}
}
int ans=0;
for(int i=1; i<=n; i++) {
if(find(i)==U)ans++;
}
cout<<ans<<endl;
}
return 0;
}
后记
祝点赞的人都有蓝勾!
另外,这么好的一篇题解,关注一下我呗。
站长曾经说过,不抄袭题解代码,只借鉴题解思路,但应该给题解点个赞,并且关注写题解的人(开玩笑的)。