中间的操作是不重要的,我们只关心最后的状态。一个点的最终状态要么确定,要么和另一个点的初始状态有关。可以开并查集合并一下,如果出现了确定的最终状态(赋值,或者 𝑥𝑖=¬𝑥𝑖)赋值即可。最终答案即为确定了必须为 𝑈 的点数。
这道题打暴力能打出来60pts的好成绩,hhh
60pts如下:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 100005;
const int T = N, F = -N, U = 0; //三值逻辑
int c, t, n, m, a, b, fa[N];
char ch[N];
bool book[N];
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;
}
满分代码如下:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int inf=1e18;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
int C,T,a[200005],b[200005],fa[200005];char op[10];
int find(int x){
return ((x==fa[x])?x:fa[x]=find(fa[x]));
}
void merge(int x,int y){
if((x=find(x))==(y=find(y)))return;
fa[x]=y;
}
void solve(){
int n=read(),m=read();
for(int i=1;i<=n;i++)a[i]=1,b[i]=i,a[i+n]=-1,b[i+n]=i;
for(int i=1;i<=m;i++){
scanf("%s",op);
if(op[0]=='+'){
int x=read(),y=read();
a[x]=a[y],b[x]=b[y];
}
else if(op[0]=='-'){
int x=read(),y=read();
a[x]=-a[y],b[x]=b[y];
}
else{
int x=read();
if(op[0]=='T')a[x]=0,b[x]=-1;
else if(op[0]=='F')a[x]=0,b[x]=-2;
else a[x]=0,b[x]=-3;
}
}
for(int i=1;i<=n+n;i++)fa[i]=i;
for(int i=1;i<=n;i++){
if(a[i]==0){
a[find(i)]=a[i],b[find(i)]=b[i];
if(b[i]!=-3)a[find(i+n)]=a[i],b[find(i+n)]=-3-b[i];
else a[find(i+n)]=a[i],b[find(i+n)]=b[i];
}
else if(a[i]==1){
if(find(i)==find(b[i]+n)){
merge(i,b[i]);merge(i+n,b[i]);
a[find(i)]=0,b[find(i)]=-3;
}
else merge(i,b[i]),merge(i+n,b[i]+n);
}
else{
if(find(i)==find(b[i])){
merge(i,b[i]+n);merge(i+n,b[i]+n);
a[find(i)]=0,b[find(i)]=-3;
}
else merge(i,b[i]+n),merge(i+n,b[i]);
}
}
int ans=0;
for(int i=1;i<=n;i++){
if(a[find(i)]==0&&b[find(i)]==-3)ans++;
}
printf("%lld\n",ans);
}
signed main(){
C=read(),T=read();
while(T--){
solve();
}
return 0;
}