[SHOI2014]神奇化合物解题报告

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


你可能感兴趣的:(DFS)