[带权并查集]小白月赛25-C 白魔法师
题目描述
你是一个白魔法师。
现在你拿到了一棵树,树上有 个点,每个点被染成了黑色或白色。
你可以释放一次魔法,将某个点染成白色。(该点不一定是黑色点,也可以是白色点)
现在释放魔法后要保证最大的白色点连通块尽可能大。请求出最大白色连通块的大小。
注:所谓白色连通块,指这颗树的某个连通子图,上面的点全部是白色。
现在你拿到了一棵树,树上有 个点,每个点被染成了黑色或白色。
你可以释放一次魔法,将某个点染成白色。(该点不一定是黑色点,也可以是白色点)
现在释放魔法后要保证最大的白色点连通块尽可能大。请求出最大白色连通块的大小。
注:所谓白色连通块,指这颗树的某个连通子图,上面的点全部是白色。
解题思路:
树上一遍dfs with 带权并查集统计联通块信息,枚举所有黑点
统计黑点的临点的联通块白色和即可
/* Zeolim - An AC a day keeps the bug away */ //#pragma GCC optimize(2) //#pragma GCC ("-W1,--stack=128000000") #include <bits/stdc++.h> using namespace std; #define mp(x, y) make_pair(x, y) #define fr(x, y, z) for (int x = y; x < z; ++x) #define pb(x) push_back(x) #define mem(x, y) memset(x, y, sizeof(x)) typedef long long ll; typedef unsigned long long ull; typedef long double ld; typedef std::pair<int, int> pii; typedef std::vector<int> vi; // typedef __int128 ill; const ld PI = acos(-1.0); const ld E = exp(1.0); const ll INF = 0x3f3f3f3f3f3f3f3f; const ll MOD = 1e9 + 7; const ull P = 13331; const int MAXN = 4e6 + 100; int n; int fa[MAXN] = {0}; int val[MAXN] = {0}; int W[MAXN] = {0}; int findfa(int x) { return x == fa[x] ? x : fa[x] = findfa(fa[x]); } vector<int> edge[MAXN]; void dfs(int now, int last) { for (auto to : edge[now]) { if (to == last) continue; if (W[now] && W[to]) { int p = findfa(now), q = findfa(to); if (p != q) { fa[p] = q; val[q] += val[p]; } } dfs(to, now); } } int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); // freopen("d:\out.txt","w",stdout); // freopen("d:\in.txt","r",stdin); cin >> n; fill(val, val + n + 10, 1); for (int i = 0; i <= n + 10; ++i) { fa[i] = i; } char x; for (int i = 1; i <= n; ++i) { cin >> x; W[i] = (x == 'W'); } for (int i = 0, x, y; i < n - 1; ++i) { cin >> x >> y; edge[x].pb(y); edge[y].pb(x); } dfs(1, 0); int ans = 0; for(int i = 1; i <= n; ++i) { ans = max(ans, val[i]); } for (int i = 1; i <= n; ++i) { if (!W[i]) { int rans = 1; set<int> used; for (auto to : edge[i]) { if (W[to]) { int p = findfa(to); if (!used.count(p)) { rans += val[p]; used.insert(p); } } } ans = max(ans, rans); } } cout << ans << '\n'; return 0; } /* 4 WBWW 1 2 2 3 3 4 */