大样例tribool4没过
思路: 先把每个变量最终变成了谁的初值记录到a数组,再把每个变量和他的最终值合并到一个集合,之后枚举每个变量,如果和自己的反变量在一个集合就把这个集合打标记,最后枚举每个变量,如果所在集合被打上了标记就ans+1
code:
#include<bits/stdc++.h>
using namespace std;
const int N = 200005;
const int vU = 200001;
const int vT = 200002;
const int vF = 200003;
int n,m;
int a[N << 2];
int T(int x,int state){
if(x == vU) return vU;
if(x == vT){
if(state) return vT;
return vF;
}
if(x == vF){
if(state) return vF;
return vT;
}
if(state) return x + N + 5;
return x;
}
int rT(int x){
if(x > N) return -(x - N - 5);
return x;
}
namespace Set{
int f[N << 2];
void init(int n){
for(int i = 1;i <= n;++ i){
f[i] = i;
}
}
int find(int w){
if(f[w] == w) return w;
return find(f[w]);
}
void merge(int x,int y){
x = find(x),y = find(y);
if(x == y) return;
f[x] = y;
}
}
bool fail[N << 2];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int c,t;
cin>>c>>t;
while(t --){
cin>>n>>m;
Set::init((N << 2) - 1);
memset(fail,0,sizeof(fail));
for(int i = 1;i <= (N << 1) + 5;++ i){
a[T(i,1)] = T(i,1);
a[T(i,0)] = T(i,0);
}
for(int i = 1;i <= m;++ i){
char op;
cin>>op;
switch(op){
case('T'):{
int x;
cin>>x;
a[T(x,1)] = T(vT,1);
a[T(x,0)] = T(vT,0);
break;
}
case('F'):{
int x;
cin>>x;
a[T(x,1)] = T(vF,1);
a[T(x,0)] = T(vF,0);
break;
}
case('U'):{
int x;
cin>>x;
a[T(x,1)] = T(vU,1);
a[T(x,0)] = T(vU,0);
break;
}
case('+'):{
int x,y;
cin>>x>>y;
a[T(x,1)] = a[T(y,1)];
a[T(x,0)] = a[T(y,0)];
break;
}
case('-'):{
int x,y;
cin>>x>>y;
a[T(x,1)] = a[T(y,0)];
a[T(x,0)] = a[T(y,1)];
break;
}
}
}
// for(int i = 1;i <= n;++ i){
// cout<<"?"<<i<<" "<<T(i,1)<<"\n";
// cout<<T(i,1)<<" <- "<<a[T(i,1)]<<"\n";
// cout<<T(i,0)<<" <- "<<a[T(i,0)]<<"\n";
// }
for(int i = 1;i <= n;++ i){
Set::merge(T(i,1),a[T(i,1)]);
Set::merge(T(i,0),a[T(i,0)]);
}
for(int i = 1;i <= n;++ i){
int g0 = Set::find(T(i,0));
int g1 = Set::find(T(i,1));
if(g0 == g1) fail[g1] = true;
}
int ans = 0;
for(int i = 1;i <= n;++ i){
if(fail[Set::find(T(i,1))]) ans ++;
}
cout<<ans<<"\n";
}
return 0;
}