题目大意:维护一张弦图,支持加边、删边和询问图中有多少个联通块
暴力题233
直接做O(qn+qm)会挂 因此我们预先将m条边中自始至终不会被删除的边用并查集缩点
这样图中的边就只有O(q)条 暴力即可
时间复杂度O(nq+q^2)
很疑惑为什么要给一张弦图- - 去找了下没看到类似于动态弦图的东西- -
#include <map> #include <vector> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 5050 using namespace std; int n,m,q; map<pair<int,int>,bool> edges; struct Query{ int type,x,y; //1-A 2-D 3-Q friend istream& operator >> (istream &_,Query &q) { char p[10]; scanf("%s",p); if(p[0]=='A') q.type=1,scanf("%d%d",&q.x,&q.y); else if(p[0]=='D') { q.type=2; scanf("%d%d",&q.x,&q.y); if( edges.find( make_pair(q.x,q.y) )!=edges.end() ) edges[make_pair(q.x,q.y)]=true; else if( edges.find( make_pair(q.y,q.x) )!=edges.end() ) edges[make_pair(q.y,q.x)]=true; } else q.type=3; return _; } }queries[10100]; vector<int> g[M]; namespace Union_Find_Set{ int fa[M],size[M]; int Find(int x) { if(!fa[x]) fa[x]=x,size[x]=1; if(fa[x]==x) return fa[x]=x; return fa[x]=Find(fa[x]); } void Union(int x,int y) { x=Find(x);y=Find(y); if(x==y) return ; if(size[x]>size[y]) swap(x,y); fa[x]=y;size[y]+=size[x]; } } using namespace Union_Find_Set; int v[M],T; void DFS(int x) { vector<int>::iterator it; v[x]=T; for(it=g[x].begin();it!=g[x].end();it++) if(v[*it]!=T) DFS(*it); } int Get_Ans() { int i,re=0;++T; for(i=1;i<=n;i++) if(Find(i)==i&&v[i]!=T) ++re,DFS(i); return re; } int main() { int i,x,y; cin>>n>>m; for(i=1;i<=m;i++) { scanf("%d%d",&x,&y); edges[make_pair(x,y)]=false; } cin>>q; for(i=1;i<=q;i++) cin>>queries[i]; map<pair<int,int>,bool>::iterator it; for(it=edges.begin();it!=edges.end();it++) { x=Find(it->first.first); y=Find(it->first.second); if(!it->second) Union(x,y); } for(it=edges.begin();it!=edges.end();it++) { x=Find(it->first.first); y=Find(it->first.second); if(it->second) g[x].push_back(y),g[y].push_back(x); } for(i=1;i<=q;i++) { if(queries[i].type==1) { x=Find(queries[i].x);y=Find(queries[i].y); g[x].push_back(y);g[y].push_back(x); } else if(queries[i].type==2) { x=Find(queries[i].x);y=Find(queries[i].y); vector<int>::iterator it; for(it=g[x].begin();it!=g[x].end();it++) if(*it==y) { g[x].erase(it); break; } for(it=g[y].begin();it!=g[y].end();it++) if(*it==x) { g[y].erase(it); break; } } else printf("%d\n",Get_Ans()); } return 0; }
原文地址:http://blog.csdn.net/popoqqq/article/details/44001667