做题的时候一上来就把时间复杂度算错了。。DFS的时间复杂度是O(n+m),我竟然给算成O(n)了!
想过来以后还是比较简单的,观察到m很大但q很小,所以可以将图删成树以得到O(q(n+q))的时间复杂度,至于UFS什么的,用不用都行。
#include<iostream>
using namespace std;
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
char * ptr=(char *)malloc(10000000);
int fa[5001],n[50000],p[5001],s[50000],qc[10000],qa[10000],qb[10000],tot=1;
bool g[5001][5001],pg[5001][5001],flag[5001];
struct ES{
int a,b;
}e[200000];
inline void in(int &x){
while(*ptr<'0'||*ptr>'9')++ptr;
x=0;
while(*ptr>47&&*ptr<58)x=x*10+*ptr++-'0';
}
inline void add(int x,int y){
n[tot]=p[x],p[x]=tot,s[tot++]=y;
}
inline void dfs(int x,int ftr){
flag[x]=0;
fa[x]=ftr;
for(int i=p[x];i;i=n[i])
if(flag[s[i]]&&g[x][s[i]]){
dfs(s[i],ftr);
}
}
inline int find(int x){
return fa[x]!=fa[fa[x]]?fa[x]=find(fa[x]):fa[x];
}
int main(){
/*----------Read------*/
fread(ptr,1,10000000,stdin);
int N,m,i,j,x,y,ans,q;
in(N),in(m);
ans=N;
for(i=0;i<m;++i){
in(x),in(y);
e[i]=(ES){x,y};
pg[x][y]=1,pg[y][x]=1;
}
in(q);
for(i=0;i<q;++i){
while(*ptr<'A'||*ptr>'Q')++ptr;
switch(*ptr++){
case 'A':
in(qa[i]),in(qb[i]);
qc[i]=1;
break;
case 'D':
in(qa[i]),in(qb[i]);
qc[i]=2;
g[qa[i]][qb[i]]=1;
g[qb[i]][qa[i]]=1;
break;
case 'Q':qc[i]=3;
}
}
/*-------Delete------*/
for(i=1;i<=N;++i)fa[i]=i;
for(i=0;i<m;++i)
if(!g[e[i].a][e[i].b]&&find(e[i].a)!=find(e[i].b)){
--ans;
fa[fa[e[i].a]]=fa[e[i].b];
add(e[i].a,e[i].b),add(e[i].b,e[i].a);
}
for(i=0;i<q;++i)
if(qc[i]==2&&pg[qa[i]][qb[i]]){
add(qa[i],qb[i]),add(qb[i],qa[i]);
if(find(qa[i])!=find(qb[i])){
--ans;
fa[fa[qa[i]]]=fa[qb[i]];
}
}
memset(g,0,sizeof(g));
for(i=1;i<=N;++i)
for(j=p[i];j;j=n[j])
g[i][s[j]]=1;
/*----UFS+DFS=ANS---*/
for(i=0;i<q;++i)
switch(qc[i]){
case 1:
g[qa[i]][qb[i]]=1,g[qb[i]][qa[i]]=1;
add(qa[i],qb[i]),add(qb[i],qa[i]);
if(find(qa[i])!=find(qb[i])){
--ans;
fa[fa[qa[i]]]=fa[qb[i]];
}
break;
case 2:
g[qa[i]][qb[i]]=0,g[qb[i]][qa[i]]=0;
fa[qb[i]]=0;
memset(flag,1,sizeof(flag));
dfs(qa[i],qa[i]);
if(!fa[qb[i]]){
++ans;
memset(flag,1,sizeof(flag));
dfs(qb[i],qb[i]);
}
break;
case 3:printf("%d\n",ans);break;
}
}