rt,本机过大样例,洛谷20pts #3~#10RE,CCF官方60pts
玄学并查集做法:
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int sub,t;
int n,m;
bool flag;
int in[100006];
int fa[100006];
int gettt[100006];
int Find(int x)
{
int tmp=x,tmp2;
while(fa[x]!=x) x=fa[x];
while(fa[tmp]!=tmp)
{
tmp2=tmp;
tmp=fa[tmp];
fa[tmp2]=x;
}
return x;
}
int Find2(int x)
{
int tmp=x;
while(fa[x]!=x)
{
if(gettt[x])
break;
x=fa[x];
}
while(fa[tmp]!=tmp&&tmp!=x)
{
gettt[tmp]=gettt[x];
tmp=fa[tmp];
}
return x;
}
int main()
{
cin>>sub>>t;
while(t--)
{
cin>>n>>m;
int _T=n+1;
int _F=-n-1;
int _U=0;
int ans=0;
for(int i=0;i<=n+1;i++)
{
gettt[i]=0;
in[i]=fa[i]=i;
}
gettt[_U]=-1;
gettt[_T]=gettt[_F]=1;
int x,y;
while(m)
{
char ch=getchar();
switch(ch)
{
case '+':cin>>x>>y;in[x]=in[y];break;
case '-':cin>>x>>y;in[x]=-in[y];break;
case 'T':cin>>x;in[x]=_T;break;
case 'F':cin>>x;in[x]=_F;break;
case 'U':cin>>x;in[x]=_U;break;
default:m++;
}
m--;
}
for(int i=1;i<=n;i++)
{
int tmpy=Find(abs(in[i]));
if(i!=tmpy)
fa[i]=tmpy;
}
for(int i=1;i<=n;i++)
{
if(fa[i]==i)
{
int now=i;
bool Unum=1;
do
{
if(in[now]<0)
{
Unum=!Unum;
}
now=abs(in[now]);
}while(now!=i);
if(Unum)
{
fa[i]=n+1;
do
{
gettt[now]=1;
now=abs(in[now]);
}while(now!=i);
}
else
{
fa[i]=0;
do
{
gettt[now]=-1;
now=abs(in[now]);
}while(now!=i);
}
}
}
for(int i=1;i<=n;i++)
{
if(!gettt[i])
{
Find2(i);
}
}
for(int i=1;i<=n;i++)
{
if(gettt[i]==-1)
ans++;
}
cout<<ans<<endl;
}
return 0;
}