思路:与团伙类似
#include<bits/stdc++.h>
using namespace std;
int t,n,m,x,y,tot;
int a[1000086],fa[1000086];
bool flag[1000086];
int foe[1000086];//某数的“敌人”,即 -x[i]
int find(int x)
{
if(fa[x]!=x)
{
return fa[x]=find(fa[x]);
}
else return fa[x];
}
void unnion(int x,int y)
{
int a=find(x);
int b=find(y);
fa[a]=b;
}
int main()
{
char s;
int c;
cin>>c>>t;
for(int z=1;z<=t;z++)
{
tot=0;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
foe[i]=0;
flag[i]=false;
fa[i]=i;
a[i]=i;
} //多测清零
for(int i=1;i<=m;i++)
{
cin>>s;
if(s=='T')
{
scanf("%d",&x);
flag[x]=false;
}
if(s=='F')
{
scanf("%d",&x);
flag[x]=false;
}
if(s=='U')
{
scanf("%d",&x);
flag[x]=true;
}
if(s=='-')
{
scanf("%d%d",&x,&y);
a[x]=a[y]*(-1);
if(x==y && foe[x]==x)//特判
{
foe[x]=0;
// cout<<x<<endl;
// cout<<foe[x]<<endl;
continue;
}
if(foe[x])unnion(foe[x],y);
else foe[x]=y;
if(foe[y])unnion(foe[y],x);
else foe[y]=x;
//“敌人的敌人就是朋友”,负负得正
if(flag[fa[y]])
{
unnion(x,y);
flag[x]=true;
cout<<"*"<<endl;
}
}
if(s=='+')
{
scanf("%d%d",&x,&y);
a[x]=a[y];
unnion(x,y);
}
}
for(int i=1;i<=n;i++)
{
int b=find(i);
if(b==find(foe[i]))//如果“敌人的朋友是朋友”,那么明显矛盾,即为 U
{
flag[b]=true;
// cout<<b<<" "<<foe[i]<<" "<<endl;
// cout<<"***"<<endl;
}
if(a[i]==-i)flag[b]=true;
// if(flag[i]=true)flag[fa[i]]=true;
}
/*for(int i=1;i<=n;i++)cout<<a[i]<<" ";
cout<<endl;
for(int i=1;i<=n;i++)
{
cout<<find(i)<<" ";
}
cout<<endl;
for(int i=1;i<=n;i++)
{
cout<<fa[i]<<" ";
}
cout<<endl;*/
for(int i=1;i<=n;i++)
{
if(flag[fa[i]])tot++;
}
cout<<tot<<endl;
}
return 0;
}