hdu 4677 并查集+离线+构造 无向图上连续区间的连通块数目
来源:互联网 发布:教育软件下载 编辑:程序博客网 时间:2024/05/20 22:38
把n个点按sqrt(n)的大小划分,第i个区间表示【1,sqrt(n)*i】的连通关系,
离线处理,从后往前边插入边询问,插入u点时,如果[u,v]的v点在区间内,就放在同一集合
有u点的询问对【u,v】时,由于v之前的那个区间的连通关系已经处理好,只须处理v所在区间的起点到v这个区间的连通关系
这个区间不超过sqrt(n)个点,每个点有m/n条边(由于数据是随机产生的),每次复杂度是m/n*sqrt(n),刚好不超,构造奇妙
#include <iostream>#include <cstdio>#include <vector>#include <cmath>#include <cstring>using namespace std;#define N 30050struct Q{ int r,idx; Q(int _r=0,int _idx=0):r(_r),idx(_idx){}};vector<Q>que[N];vector<int>edge[N];int fa[N][200],scc[200],rr[200];int ta[N],first[N],ans[N];int n,m,tot,every;int find(int i,int pos){ return fa[i][pos]==i?i:fa[i][pos]=find(fa[i][pos],pos);}void init(){ for(int i=0;i<=n;++i) edge[i].clear(),que[i].clear(); memset(scc,0,sizeof(scc)); every=tot=sqrt(n*1.0); if(n*n!=tot) tot++; for(int i=0;;++i) { rr[i]=i*every; if(i*every>=n) break; } for(int i=0;i<=tot;++i) for(int j=0;j<=n;++j) fa[j][i]=j; memset(first,-1,sizeof(first));}int main (){ int T;scanf("%d",&T); for(int kk=1;kk<=T;++kk) { scanf("%d%d",&n,&m); init(); for(int i=1,u,v;i<=m;++i) { scanf("%d%d",&u,&v); if(u==v) continue; edge[u].push_back(v); edge[v].push_back(u); } int q;scanf("%d",&q); for(int i=1,u,v;i<=q;++i) { scanf("%d%d",&u,&v); que[u].push_back(Q(v,i)); } int run_clock=0; for(int u=n;u>=1;--u) { for(int j=1;j<=tot;++j) { if(u>rr[j]) continue; scc[j]++; int inc=0; for(int i=0;i<edge[u].size();++i) { int v=edge[u][i]; if(u<v&&v<=rr[j]) { int u1=find(u,j); int v1=find(v,j); if(u1!=v1) { inc++; fa[v1][j]=u1; } } } scc[j]-=inc; } for(int z=0;z<que[u].size();++z) { run_clock++; int right=que[u][z].r; int pos;int inc=0; for(pos=0;pos<tot;++pos) if(rr[pos]<right&&right<=rr[pos+1]) break; for(int i=max(u+1,rr[pos]+1);i<=right;++i) { if(first[i]!=run_clock) { first[i]=run_clock; fa[i][tot+1]=i; } for(int j=0;j<edge[i].size();++j) if(u<=edge[i][j]&&edge[i][j]<i) { int v1=find(edge[i][j],pos); if(first[v1]!=run_clock) { first[v1]=run_clock; fa[v1][tot+1]=v1; } if(find(i,tot+1)!=find(v1,tot+1)) { fa[find(v1,tot+1)][tot+1]=find(i,tot+1); inc++; } } } ans[que[u][z].idx]=scc[pos]+right-max(rr[pos],u-1)-inc; } } printf("Case #%d:\n",kk); for(int i=1;i<=q;++i) printf("%d\n",ans[i]); } return 0;}
- hdu 4677 并查集+离线+构造 无向图上连续区间的连通块数目
- 计算无向图中连通块的数目
- [容易] 并查集的优雅实现(实例:求无向图最大连通块结点数)
- 无向图连通判断(并查集)
- 使用并查集判断无向图是否连通
- 并查集——求无向图的所有连通子图
- 图中连通块的个数:并查集
- (并查集)求给定图G的连通分量的数目
- 无向图求连通块的个数问题
- hdu 1272小希的迷宫(并查集判断无向图回路)
- HDU 1272 小希的迷宫【并查集判断无向图回路】
- hdu 3938(离线的并查集)
- Tarjan应用:无向图删点后剩余的连通分支数目
- 【HDU 4514】【树的直径 dfs或者并查集判断环】【给定一个无向图,图可能是非连通的,如果图中存在环,就输出YES,否则就输出树的直径】
- 无向图的连通性问题(并查集)
- 无向图 多余的链接(并查集)
- 并查集判断连通块个数
- hdoj 5441 Travel 【在边权限制下 并查集划分、合并连通块,求解点对数目】
- 职业生涯规划
- IE10下, 调用ajax问题
- 【浅析Win7系统的移动中心以及打开&关闭】
- 关机,注销,重启函数:ExitWindowsEx
- 总结一些使用visual studio的tips(不断更新)
- hdu 4677 并查集+离线+构造 无向图上连续区间的连通块数目
- 关于函数调用过程中的实参和形参问题
- 【win8键盘快捷键大全】
- IntentService总结
- SecureCRT 文件名彩色 (ubuntu13.04)
- 一些很好的工控机硬件平台
- [转载]JavaScript世界的一等公民 - 函数
- hdu 1573 X问题 中国剩余定理(直接模板就OK了)
- ios构造函数