JZOJ 3453【NOIP2013中秋节模拟】连通块
2016-07-08 16:14
411 查看
原题
Description
你应该知道无向图的连通块的数量,你应该知道如何求连通块的数量。当你兴奋与你的成就时,破坏王Alice拆掉了图中的边。当她发现,每删去一条边,你都会记下边的编号,同时告诉她当前连通块的个数。然而,对边编号简直就是个悲剧,因为Alice为了刁难你,拆掉编号从l到r的边,当然你需要做的事情就是求连通块的个数。如果你答对了,Alice会把拆掉的边装好,迚行下一次破坏。如果你无法完成这个任务,Alice会彻底毁了你的图。
进行完足够多次之后,Alice觉得无聊,就玩去了,而你却需要继续做第三题。
Input
第一行两个整数n,m,表示点数和边数。之后m行每行两个整数x,y,表示x与y之间有无向边。(按读入顺序给边编号,编号从1开始)
一行一个整数k,表示Alice的破坏次数。
之后k行,每行两个整数l,r。
Output
k行,每行一个整数。Sample Input
6 51 2
5 4
2 3
3 1
3 6
6
1 3
2 5
1 5
5 5
2 4
3 3
Sample Output
45
6
3
4
2
Data Constraint
对于30%的数据,n<=100,k<=10对于60%的数据,k<=1000
对于100%的数据,n<=500,m<=10000,k<=20000,1<=l<=r<=m
题解
并查集。Collect!每一个 f[i] 为一个并查集,记录只添加前 i 条边时,所有节点的联通情况。
每一个 g[i] 也是一个并查集,记录只添加 i—m 条边时,所有节点的联通情况。
对于每个询问只要把 f[l−1] 和 g[r+1] 合并至 H[] 中。
最后在 H[] 中判断即可。
Code
#include<cstdio> #include<cstring> using namespace std; int n,m; struct data { int x,y; }a[10002]; int f[10002][501],g[10002][501],h[501]; inline int read() { int data=0; char ch=0; while(ch<'0' || ch>'9') ch=getchar(); while(ch>='0' && ch<='9') data=data*10+ch-'0',ch=getchar(); return data; }//读入优化 inline int getf(int k,int x) { if(f[k][x]==x) return x; return f[k][x]=getf(k,f[k][x]); }//F的查找 inline int getg(int k,int x) { if(g[k][x]==x) return x; return g[k][x]=getg(k,g[k][x]); }//G的查找 void init() { n=read(); m=read(); for(int i=1;i<=m;i++) a[i].x=read(),a[i].y=read(); for(int i=1;i<=n;i++) f[0][i]=g[m+1][i]=i;//初值 for(int i=1;i<=m;i++) { memcpy(f[i],f[i-1],sizeof(f[i])); f[i][getf(i,a[i].x)]=getf(i,a[i].y); }//F的处理 for(int i=m;i;i--) { memcpy(g[i],g[i+1],sizeof(g[i])); g[i][getg(i,a[i].x)]=getg(i,a[i].y); }//G的处理 } inline int geth(int x) { if(h[x]==x) return x; return h[x]=geth(h[x]); }//H的查找 void work() { int k=read(); while(k--) { int l=read()-1,r=read()+1; memcpy(h,f[l],sizeof(h)); for(int i=1;i<=n;i++) h[geth(h[i])]=geth(g[r][i]);//H的处理 int ans=0; for(int i=1;i<=n;i++) if(h[i]==i) ans++;//H的判断 printf("%d\n",ans); } } int main() { freopen("connect.in","r",stdin); freopen("connect.out","w",stdout); init(); work(); return 0; }
相关文章推荐
- 修改数据表
- union 与union all的区别
- String是final类,常规情况下其值是不可变的。但是可以通过非常规方法——反射进行修改
- 消息队列设计精要
- mybatis中的#{}和${}的区别
- Varnish4.1.2代理缓存
- 根据两点经纬度计算距离
- django URL学习
- 完整的申请邓白氏编码的流程(手把手教你申请邓白氏编码)
- Caused by: android.content.res.Resources$NotFoundException: String resource ID #0x1
- 喷码机报300V电源故障
- Java---三种文件拷贝的实现方法
- 练习20——函数和文件
- 记录一个android的代码网址
- Linux下启动Oracle服务和监听程序
- Android Studio的内存泄漏检测与解决
- Oracle安装后的默认账号以及一些基本操作
- UVA - 10474 Where is the Marble?
- 【noip暑假tarjan专题】
- cocos2dx中的声音