bzoj 4998 星球联盟

编程入门 行业动态 更新时间:2024-10-14 04:28:23

bzoj 4998 <a href=https://www.elefans.com/category/jswz/34/1760928.html style=星球联盟"/>

bzoj 4998 星球联盟

新技能 get √ :LCT 维护边双连通分量

 

这题题意就是动态加边,每次求边的两端是否在一个边双连通分量里,输出 "No" 或者边双连通分量的大小

可以用两个并查集分别记录连通性和双连通性,如果还没连通就是 "No" 并在 LCT 上连边,否则直接把这条链 split 出来查即可

注意 LCT 维护的是双连通分量,所以每次跳 fa 的时候不再是 fa,而是 fa 所在的双连通分量

#include <bits/stdc++.h>
#define LL long long
#define rep(i, s, t) for (register int i = (s), i##end = (t); i <= i##end; ++i)
#define dwn(i, s, t) for (register int i = (s), i##end = (t); i >= i##end; --i)
using namespace std;
inline int read() {int x = 0,f = 1; char ch = getchar();for(; !isdigit(ch); ch = getchar())if(ch == '-') f = -f;for(; isdigit(ch); ch = getchar())x = 10 * x + ch - '0';return x * f;
}
const int maxn = 200010;
int par[maxn], par2[maxn], size[maxn], ans;
inline int find(int x) {return x == par[x] ? x : par[x] = find(par[x]);}
inline int find2(int x) {return x == par2[x] ? x : par2[x] = find2(par2[x]);}
int n, m, p;
#define ls ch[x][0]
#define rs ch[x][1]
int ch[maxn][2], fa[maxn], rev[maxn], st[maxn], top;
inline int isroot(int x) { return ch[find(fa[x])][0] != x && ch[find(fa[x])][1] != x; }
inline void pushdown(int x) {if(rev[x]) {swap(ls, rs); if(ls) rev[ls] ^= 1; if(rs) rev[rs] ^= 1;rev[x] = 0;}
}
inline void rotate(int x) {int y = find(fa[x]), z = find(fa[y]);int l = (ch[y][1] == x), r = l ^ 1;if(!isroot(y)) ch[z][ch[z][1] == y] = x;fa[x] = z; fa[ch[x][r]] = y; fa[y] = x;ch[y][l] = ch[x][r]; ch[x][r] = y;
}
inline void splay(int x) {st[top = 1] = x;for(int i=x;!isroot(i);i=find(fa[i])) st[++top] = find(fa[i]);for(int i=top;i;i--) pushdown(st[i]);//PUSHDOWN(x);//cout << x << endl;while(!isroot(x)) {int y = find(fa[x]), z = find(fa[y]);if(!isroot(y)) {if(ch[z][0] == y ^ ch[y][0] == x) rotate(x);else rotate(y);} rotate(x);}
}
inline void access(int x) {for(int y = 0; x; splay(x), rs = y, y = x, x = find(fa[x]));
}
inline void makeroot(int x) {access(x); splay(x); rev[x] ^= 1;
}
inline void link(int x, int y) {makeroot(x); fa[x] = y;
}
void dfs(int x, int pre) {if(!x) return;ans += size[x];if(x != pre) size[pre] += size[x], par[x] = pre;dfs(ls, pre); dfs(rs, pre);
}
inline void lnk(int u, int v) {ans = 0;if(find2(u) != find2(v)) {par2[par2[u]] = par2[v];//cout << u << " " << v << endl;
        link(u, v);}else {makeroot(u); access(v); splay(v); dfs(v, v);}
}
int main() {n = read(), m = read(), p = read();rep(i, 1, n) size[i] = 1, par[i] = i, par2[i] = i;rep(i, 1, m) {int u = find(read()), v = find(read());lnk(u, v);}rep(i, 1, p) {int u = find(read()), v = find(read()); lnk(u, v);printf(ans ? "%d\n" : "No\n", ans);}
}
View Code

 

转载于:.html

更多推荐

bzoj 4998 星球联盟

本文发布于:2024-02-07 02:40:51,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1752450.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:星球   联盟   bzoj

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!