jzoj 3453_连通块_并查集
来源:互联网 发布:手机剪辑视频软件 编辑:程序博客网 时间:2024/05/20 20:57
题目描述
你应该知道无向图的连通块的数量,你应该知道如何求连通块的数量。当你兴奋与你的成就时,破坏王Alice拆掉了图中的边。当她发现,每删去一条边,你都会记下边的编号,同时告诉她当前连通块的个数。
然而,对边编号简直就是个悲剧,因为Alice为了刁难你,拆掉编号从l到r的边,当然你需要做的事情就是求连通块的个数。如果你答对了,Alice会把拆掉的边装好,迚行下一次破坏。如果你无法完成这个任务,Alice会彻底毁了你的图。
进行完足够多次之后,Alice觉得无聊,就玩去了,而你却需要继续做第三题。
思路
两个并查集,f[i]表示前i条边所连成的点的集合,g[j]表示后j条边所连成的点的集合。 那么对于一个询问 [l,r],我们就可以通过合并f[l-1]和g[r+1]两个集合来确定有几个联通块
#include <stdio.h>#include <cstring>using namespace std;int n, m;#define fill(x, y) memset(x, y, sizeof(x))int f[10005][501], g[10005][501], a[10001][3], fl[501];__attribute__((optimize("-O2")))inline int find(int x, int t){ //if (t > m || t < 1) return 0; if (!f[t][x]) return x; f[t][x] = find(f[t][x], t); return f[t][x];}__attribute__((optimize("-O2")))inline int insert(int x, int y, int t){ if (find(x, t) != find(y, t)) { f[t][find(x, t)] = find(y, t); return 0; } return 0;}__attribute__((optimize("-O2")))inline int find1(int x, int t){ //if (t > m || t < 1) return 0; if (!g[t][x]) return x; g[t][x] = find1(g[t][x], t); return g[t][x];}__attribute__((optimize("-O2")))inline int insert1(int x, int y, int t){ //int xx = find1(x, t), yy = find1(y, t); if (find1(x, t) != find1(y, t)) { g[t][find1(x, t)] = find1(y, t); return 0; } return 0;}__attribute__((optimize("-O2")))inline int find2(int x){ if (!fl[x]) return x; fl[x] = find2(fl[x]); return fl[x];}__attribute__((optimize("-O2")))inline int insert2(int x, int y, int r){ int xx = find2(x), yy = find2(y); if (xx != yy) { fl[xx] = yy; return 0; } return 0;}int main(){ freopen("connect.in","r",stdin); freopen("connect.out","w",stdout); scanf("%d%d", &n, &m); for (int i = 1; i <= m; i++) { int x, y; scanf("%d%d", &x, &y); a[i][1] = x; a[i][2] = y; for (int j = 1; j <= n; j++) { f[i][j] = f[i - 1][j]; } insert(x, y, i); } for (int i = m; i >= 1; i--) { int x = a[i][1], y = a[i][2]; for (int j = 1; j <= n; j++) { g[i][j] = g[i + 1][j]; } insert1(x, y, i); } int t; scanf("%d", &t); for (int i = 1; i <= t; i++) { int l, r; scanf("%d%d", &l, &r); int ans = 0; for (int j = 1; j <= n; j++) fl[j] = f[l - 1][j]; for (int j = 1; j <= n; j++) { if (find2(j) != find1(j , r + 1)) { insert2(find2(j), find1(j ,r + 1), r + 1); } } for (int j = 1; j <= n; j++) if (fl[j] == 0) ans++; printf("%d\n", ans); }}
阅读全文
1 1
- jzoj 3453_连通块_并查集
- 连通分量个数(连通分量_并查集)
- 并查集判断连通块个数
- 图论_并查集
- 并查集_食物链
- 并查集_ 模板
- 图中连通块的个数:并查集
- HDOJ1232. 畅通工程(并查集连通块计数)
- BZOJ 1015 [JSOI2008]星球大战starwar(连通块+并查集)
- JZOJ 3453【NOIP2013中秋节模拟】连通块
- hdu 1878_欧拉回路_并查集
- poj 1182_食物链_并查集
- SSL 1255_银河英雄传说_并查集
- codevs 2597_团伙_并查集
- SSL 1662_家庭问题_并查集
- POJ1182_食物链_并查集
- 叠箱子_并查集
- 并查集_感染者
- 快速复制大文件、多个文件
- 多选框select美化chosen.js的使用
- TCP协议字段中的URG和PSH
- jzoj3453【NOIP2013中秋节模拟】连通块(connect,并查集,二维)
- java 对象集合去重记录
- jzoj 3453_连通块_并查集
- Java中数组的简单使用
- android动画—alpha
- EF中Unable to create a constant value of type...的错误解决
- OpenCV遍历和输出Mat矩阵中数据方法总结
- 5-2 寻找大富翁 (25分)
- C语言各个数据类型字节数
- Android-SharedPreferences实现记住密码和自动登录
- postgresql数据库查询当前数据库、当前用户