做法大概就是只关心来自哪个初始值。
个人认为这样只会产生自环,实则不然。
考场代码写得比较屎山。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int c,T,n,m,from[N],fa[N],siz[N],tot;
char op[N];
vector<pair<int,char> > G[N];
vector<pair<int,int> > g;
void dfs(int u){
for(auto H:G[u]){
int v=H.first;
char c=H.second;
if(c=='+') op[v]=op[u];
else if(op[u]=='T') op[v]='F';
else if(op[u]=='F') op[v]='T';
else op[v]='U';
from[v]=-1;
dfs(v);
}
}
inline void make(int n){ for(int i=1;i<=n;++i) fa[i]=i; }
int find(int x){ return fa[x]=(fa[x]==x?x:find(fa[x])); }
void merge(int u,int v){
int a=find(u),b=find(v);
if(a==b) return;
if(siz[a]<siz[b]) fa[a]=b,siz[b]+=siz[a];
else fa[b]=a,siz[a]+=siz[b];
}
void init(int u,int t,int flg){
if(u==t&&~flg) return;
++tot;
for(auto H:G[u]){
int v=H.first;
char c=H.second;
if(c=='+') op[v]=op[u];
else if(op[u]=='+') op[v]='-';
else op[v]='+';
from[v]=from[u];
init(v,t,1);
}
}
inline int read(){
int res=0;
char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') res=(res<<1)+(res<<3)+(ch^'0'),ch=getchar();
return res;
}
void write(int x){
if(x>=10) write(x/10);
putchar((x%10)^'0');
}
int main(){
c=read(),T=read();
while(T--){
n=read(),m=read();
for(int i=1;i<=n;++i) from[i]=i,op[i]='?',G[i].clear(),G[i].shrink_to_fit();
g.clear(),g.shrink_to_fit();
while(m--){
char OP=getchar();
while(OP!='+'&&OP!='-'&&OP!='T'&&OP!='F'&&OP!='U') OP=getchar();
if(OP=='+'){
int i=read(),j=read();
if(op[j]=='?') op[i]='+',from[i]=from[j];
else if(op[j]=='+'||op[j]=='-') op[i]=op[j],from[i]=from[j];
else op[i]=op[j],from[i]=-1;
} else if(OP=='-'){
int i=read(),j=read();
if(op[j]=='?') op[i]='-',from[i]=j;
else if(op[j]=='+') op[i]='-',from[i]=from[j];
else if(op[j]=='-') op[i]='+',from[i]=from[j];
else if(op[j]=='T') op[i]='F',from[i]=-1;
else if(op[j]=='F') op[i]='T',from[i]=-1;
else op[i]='U',from[i]=-1;
} else{
int i=read();
op[i]=OP,from[i]=-1;
}
}
for(int i=1;i<=n;++i) if(from[i]==i&&op[i]=='-') op[i]='U',from[i]=-1;
for(int i=1;i<=n;++i) if(~from[i]) G[from[i]].push_back(make_pair(i,op[i]));
for(int i=1;i<=n;++i) if(op[i]=='T'||op[i]=='F'||op[i]=='U') dfs(i);
int cnt=0;
for(int i=1;i<=n;++i) cnt+=(op[i]=='U');
make(n);
for(int i=1;i<=n;++i) if(~from[i]){
if(find(from[i])==find(i)) g.push_back(make_pair(i,from[i]));
else merge(from[i],i);
}
for(auto p:g){
tot=0;
init(p.first,p.first,-1);
if(from[p.second]==p.second&&op[p.second]=='-') op[p.second]='U',from[p.second]=-1,cnt+=tot;
}
write(cnt),putchar('\n');
}
return 0;
}