[带权并查集]小白月赛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
*/

 

posted @ 2020-05-18 09:42  张浦  阅读(277)  评论(0编辑  收藏  举报