大水题来啦!!
就是一个暴力题啊!!!
一开始想到了。。。
但是由于我太弱了,觉得10000*10000会超时,于是就GG了。。
不知道为什么。。我都做了这么多题了。。还不是非常清楚多少复杂度会超时。。看来还是我太弱了啊
这题的解法:
离线缩点啊!!!
然后因为询问少,所以有些边是永远在的,吧这些搞着先就好了
时间
O(q∗q+q∗n)
code:
#include<cstdio>
#include<cstring>
#define swap(x,y) {int tt=x;x=y;y=tt;}
const int N=5005;
const int Q=10005;
int n,m,q;
bool g[N][N];//是否连通
int f[N];//并查集缩点
int tt[N][N],lalal;//会变的边 这条边的新编号
int X[Q],Y[Q];
bool ooo[Q];
struct qq
{
char ss[5];int x,y;
}s[Q];
int ff[N];
int find (int x){return f[x]==x?f[x]:f[x]=find(f[x]);}
int find1 (int x){return ff[x]==x?ff[x]:ff[x]=find1(ff[x]);}
int ans[Q],cnt;
bool ok[N];
int main()
{
memset(f,false,sizeof(f));
scanf("%d%d",&n,&m);
for (int u=1;u<=n;u++) f[u]=u;
for (int u=1;u<=m;u++)
{
int x,y;
scanf("%d%d",&x,&y);
if (x>y) swap(x,y);
g[x][y]=true;
}
scanf("%d",&q);
memset(tt,-1,sizeof(tt));
for (int u=1;u<=q;u++)
{
scanf("%s",s[u].ss);
if (s[u].ss[0]=='Q') continue;
scanf("%d%d",&s[u].x,&s[u].y);
if (s[u].x==s[u].y) {u--;q--;continue;}
if (s[u].x>s[u].y) swap(s[u].x,s[u].y);
g[s[u].x][s[u].y]=(s[u].ss[0]=='A');
if (tt[s[u].x][s[u].y]==-1)
{
tt[s[u].x][s[u].y]=++lalal;
X[lalal]=s[u].x;Y[lalal]=s[u].y;
}
}
for (int u=1;u<=n;u++)
{
for (int i=u+1;i<=n;i++)
{
if (g[u][i]==true&&tt[u][i]==-1)
{
int fx=find(u),fy=find(i);
if (fx==fy) continue;
f[fx]=fy;
}
}
}
for (int u=1;u<=lalal;u++) ooo[u]=g[X[u]][Y[u]];
cnt=0;
memset(ok,false,sizeof(ok));
for (int O=q;O>=1;O--)
{
if (s[O].ss[0]=='Q')
{
cnt++;ans[cnt]=0;
for (int i=1;i<=n;i++) ff[i]=f[i];
for (int i=1;i<=lalal;i++)
{
if (ooo[i]==true)
{
int fx=find1(X[i]),fy=find1(Y[i]);
if (fx==fy) continue;
ff[fx]=fy;
}
}
for (int u=1;u<=n;u++) ok[find1(u)]=true;
for (int u=1;u<=n;u++)
if (ok[u])
{
ans[cnt]++;
ok[u]=false;
}
}
else ooo[tt[s[O].x][s[O].y]]=!(s[O].ss[0]=='A');
}
for (int u=cnt;u>=1;u--) printf("%d\n",ans[u]);
return 0;
}