做题的时候一上来就把时间复杂度算错了。。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; } }