牛客练习赛39 D 动态连通块+并查集 X bitset 优化
https://ac.nowcoder.com/acm/contest/368/D
题意
小T有n个点,每个点可能是黑色的,可能是白色的。
小T对这张图的定义了白连通块和黑连通块:
白连通块:图中一个点集V,若满足所有点都是白点,并且V中任意两点都可以只经过V中的点互相到达,则称V中的点构成了一个白连通块。
黑连通块:类似白连通块的定义。
小T对这n个点m次操作。
1、在两个点之间连一条边。
2、询问白(黑)连通块个数。
3、给出x,y两个点,保证同色(为了方便描述,x,y都是白点,黑色同理)。询问存在多少个黑点,将它改变颜色后,x,y所在的白连通块会合并为一个。如果x,y已经在一个白连通块内了,输出-1。(注意:这里不会对点的颜色改变,只统计个数)
思路
感觉这个并查集还是很妙的,颜色相同的想要合并就按照正常的并查集来。如果颜色不同,直接合并没有意义,用bitset记录下来,两个白点如果bitset中有相同的黑点,那么这个点就是第三问中的一个合法点。
#include <algorithm> #include <iterator> #include <iostream> #include <cstring> #include <cstdlib> #include <iomanip> #include <bitset> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <stack> #include <cmath> #include <queue> #include <list> #include <map> #include <set> #include <cassert> using namespace std; #define lson (l, mid, rt << 1) #define rson (mid + 1, r, rt << 1 | 1) #define debug(x) cerr << #x << " = " << x << "\n"; #define pb push_back #define pq priority_queue typedef long long ll; typedef unsigned long long ull; //typedef __int128 bll; typedef pair<ll, ll> pll; typedef pair<int, int> pii; typedef pair<int, pii> p3; //priority_queue<int> q;//这是一个大根堆q //priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q #define fi first #define se second //#define endl '\n' #define boost \ ios::sync_with_stdio(false); \ cin.tie(0) #define rep(a, b, c) for (int a = (b); a <= (c); ++a) #define max3(a, b, c) max(max(a, b), c); #define min3(a, b, c) min(min(a, b), c); const ll oo = 1ll << 17; const ll mos = 0x7FFFFFFF; //2147483647 const ll nmos = 0x80000000; //-2147483648 const int inf = 0x3f3f3f3f; const ll inff = 0x3f3f3f3f3f3f3f3f; //18 const int mod = 1e9 + 7; const double esp = 1e-8; const double PI = acos(-1.0); const double PHI = 0.61803399; //黄金分割点 const double tPHI = 0.38196601; template <typename T> inline T read(T &x) { x = 0; int f = 0; char ch = getchar(); while (ch < '0' || ch > '9') f |= (ch == '-'), ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x = f ? -x : x; } inline void cmax(int &x, int y) { if (x < y) x = y; } inline void cmax(ll &x, ll y) { if (x < y) x = y; } inline void cmin(int &x, int y) { if (x > y) x = y; } inline void cmin(ll &x, ll y) { if (x > y) x = y; } /*-----------------------showtime----------------------*/ const int maxn = 5e4 + 9; int col[maxn], fa[maxn]; bitset<50009> b[maxn], tmp; int ans[2]; int find(int x) { if (fa[x] == x) return x; return fa[x] = find(fa[x]); } void uni(int x, int y) { int fx = find(x), fy = find(y); if (col[x] == col[y]) { if (fx != fy) { fa[fx] = fy; ans[col[x]]--; b[fy] |= b[fx]; } } else b[fx].set(y), b[fy].set(x); } void cal(int x, int y) { int fx = find(x), fy = find(y); if (fx == fy) puts("-1"); else { tmp = b[fx] & b[fy]; printf("%d\n", (int)tmp.count()); } } int main() { int n, m; scanf("%d%d", &n, &m); rep(i, 1, n) scanf("%d", &col[i]), fa[i] = i, ans[col[i]]++; while (m--) { int op; scanf("%d", &op); if (op == 1) { int x, y; scanf("%d%d", &x, &y); uni(x, y); } else if (op == 2) { int x; scanf("%d", &x); printf("%d\n", ans[x]); } else { int x, y; scanf("%d%d", &x, &y); cal(x, y); } } return 0; }
skr