三值逻辑-并查集
三值逻辑-并查集
题意
在三值逻辑中, \(T\) 为真, \(F\) 为假,\(U\) 为未确定,定义 \(\lnot U = U\),接下来给出 \(n\) 个值的 \(m\) 条赋值表达式,最后的值等于初始值的情况下,问最少有几个 \(U\) 。
思路
看着这种相互取反,很容易想到使用扩展域并查集(二分图我们想到)。但是我在考试的时候总想着怎么把赋值语句在并查集中表达出来,虽然是错误的,但我还是想要分享一下。很容易发现如果 \(a\) 在给其他位置数赋值后被其他位置赋值,则这个 \(a\) 不应该和之前的点在一个并查集,但它的儿子却不应该动。所以我想到了原本的两个根并,变成了一个点直接被接到另一个根下,但如果没被赋值过,则它应该带着儿子,否则不能。这里带不带就成了我的思路的实现难点。
现在来说一下正解。容易发现我们的初始状态只和最终状态(关系)有关废话,直接在赋值的时候维护整个并查集并不好写,但是只维护这个点位置上的值(关系)很好写。简单维护出每个点上的关系之后放扩展域并查集就很好写了。
code
#include <bits/stdc++.h>
#define int long long
using namespace std;
constexpr int maxn = 3e5+10;
void read(int &);
int sub;
int fa[maxn];
int n,m;
int zhi[maxn];
inline void init(int n)
{
for(int i=1,i_ed=n*2+4 ;i<=i_ed;++i)
{
fa[i]=i;
zhi[i]=i;
}
//2*n+1-T 2*n+2-F 2*n+3-U
}
int finr(int x)
{
return x==fa[x] ? x : fa[x]=finr(fa[x]);
}
inline void join(int x,int y)
{
int xr=finr(x);
int yr=finr(y);
if(xr!=yr)
{
fa[xr]=yr;
}
}
inline int opp(int x)
{
if(x>2*n)
{
if(x==2*n+1)// 这里要注意F和T的取反
{
return x+1;
}
else if(x==2*n+2)
{
return x-1;
}
return x;
}
if(x>n)
{
return x-n;
}
return x+n;
}
void solve()
{
read(n);
read(m);
init(n);
int T=2*n+1;
int F=2*n+2;
int U=2*n+3;
char c;
for(int i=1,u,v ;i<=m;++i)
{
scanf(" %c",&c);
read(v);
if(c=='T')
{
zhi[v]=T;
zhi[v+n]=F;
}
else if(c=='F')
{
zhi[v]=F;
zhi[v+n]=T;
}
else if(c=='U')
{
zhi[v]=U;
zhi[v+n]=U;
}
else if(c=='+')
{
read(u);
zhi[v+n]=opp(zhi[u]);// 这里注意先作v+n,因为v可能等于u
zhi[v]=zhi[u];
}
else if(c=='-')
{
read(u);
zhi[v+n]=zhi[u];
zhi[v]=opp(zhi[u]);
}
}
for(int i=1;i<=n;++i)
{
join(i,zhi[i]);
join(i+n,zhi[i+n]);
}
for(int i=1;i<=n;++i)
{
if(finr(i)==finr(i+n))
{
join(i,U);
}
}
int ans=0;
for(int i=1;i<=n;++i)
{
if(finr(i)==finr(U))
{
++ans;
}
}
printf("%lld\n",ans);
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("tribool.in","r",stdin);
freopen("tribool.out","w",stdout);
#endif // ONLINE_JUDGE
int t;
read(sub);
read(t);
while(t--)
{
solve();
}
return 0;
}
inline void read(int &x)
{
x=0;
int f=1;
signed c=getchar();
while(!isdigit(c))
{
if(c=='-')
{
f=-1;
}
c=getchar();
}
while(isdigit(c))
{
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
x*=f;
}

浙公网安备 33010602011771号