1. 程式人生 > >BZOJ4998: 星球聯盟 並查集

BZOJ4998: 星球聯盟 並查集

Descripition 給你一張圖,每次加一條邊,加完邊後,問這兩個點是否屬於同一個點雙,不是輸出No,否則輸出點雙的點數。

Sample Input 5 3 4 1 2 4 3 4 5 2 3 1 3 4 5 2 4

Sample Output No 3 2 5

對於每一次加邊,就相當於把當前樹上的一段合成一點,這個可用並差集搞。 問題是如何構造出一棵樹,這個也很簡單,一開始先加完所有的邊,建出一棵樹即可。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; int read() { int s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();} while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar(); return s * f; } struct node { int x, y; } q1[210000], q2[210000
]; struct edge { int x, y, next; } e[410000]; int len, last[210000]; int fa[210000], dep[210000], f[210000]; int ff[210000], tot[210000]; int findfa(int x) { if(fa[x] != x) fa[x] = findfa(fa[x]); return fa[x]; } int findfa2(int x) { if(ff[x] != x) ff[x] = findfa2(ff[x]); return ff[x]; } void Merge(int x, int
y) { x = findfa2(x), y = findfa2(y); while(x != y) { if(dep[x] > dep[y]) swap(x, y); int fy = findfa2(f[y]); ff[y] = fy; tot[fy] += tot[y]; y = fy; } } void ins(int x, int y) { e[++len].x = x; e[len].y = y; e[len].next = last[x]; last[x] = len; } void dfs(int x) { for(int k = last[x]; k; k = e[k].next) { int y = e[k].y; if(y != f[x]) f[y] = x, dep[y] = dep[x] + 1, dfs(y); } } int main() { int n = read(), m = read(), q = read(); for(int i = 1; i <= n; i++) fa[i] = i; for(int i = 1; i <= m; i++) { int x = read(), y = read(); int fx = findfa(x), fy = findfa(y); if(fx != fy) ins(x, y), ins(y, x), fa[fx] = fy; q1[i].x = x, q1[i].y = y; } for(int i = 1; i <= q; i++) { int x = read(), y = read(); int fx = findfa(x), fy = findfa(y); if(fx != fy) ins(x, y), ins(y, x), fa[fx] = fy; q2[i].x = x, q2[i].y = y; } for(int i = 1; i <= n; i++) if(!dep[i]) dep[i] = 1, dfs(i); for(int i = 1; i <= n; i++) fa[i] = i, ff[i] = i, tot[i] = 1; for(int i = 1; i <= m; i++) { int x = q1[i].x, y = q1[i].y; int fx = findfa(x), fy = findfa(y); if(fx != fy) fa[fx] = fy; else Merge(x, y); } for(int i = 1; i <= q; i++) { int x = q2[i].x, y = q2[i].y; int fx = findfa(x), fy = findfa(y); if(fx != fy) fa[fx] = fy, printf("No\n"); else Merge(x, y), printf("%d\n", tot[findfa2(x)]); } return 0; }