白魔法师
涉及知识点:
solution:
- \(这道题目和2020寒假训练营1的F题是一个套路(毕竟出题人也是同一个人\)
- \(简述一种并查集做法:\)
- \(如果并查集不知道是啥,看样子咕了好多次每日一题了哦!\)
- \(我们先预处理所有相邻的白色节点\)
- \(对于每个白色节点,通过深搜计算所有和其联通的白色节点个数\)
- \(并将该联通的白色节点通过并查集记为同一个集合\)
- \(题目要求,我们只可以将一个节点,变成白色\)
- \(所以我们枚举每一个黑色节点,假设将这个节点染成白色\)
- \(将这个黑色节点变成白色产生的最大联通白色节点个数是多少?\)
- \(其实就等于这个黑色节点相连的所有白色节点对应的集合 + 1\)
- \(实在不理解上图!\)
std:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 1e5+5;
int a[maxn],b[maxn],f[maxn],flag[maxn];
vector<int> v[maxn];
int find(int x){
return f[x] == x ? x : (f[x] = find(f[x]));
}
void unite(int x,int y){
x = find(x),y = find(y);
if(x != y)
f[y] = x;
}
int dfs(int x,int fa){
int cnt = 1;
for(int i=0;i<v[x].size();i++){
if(flag[v[x][i]] == 0 && a[v[x][i]] == 1){
unite(x,v[x][i]);
flag[v[x][i]] = 1;
cnt += dfs(v[x][i],x);
}
}
return cnt;
}
int main()
{
int n;
char c;
scanf("%d",&n);
for(int i=1;i<=n;i++){
cin>>c;
f[i] = i;
if(c == 'W')a[i] = 1;
}
for(int i=1;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
v[x].push_back(y);
v[y].push_back(x);
}
int ans = 0;
for(int i=1;i<=n;i++){
if(flag[i] == 0 && a[i] == 1){
flag[i] = 1;
int x = dfs(i , 0);
int y = find(i);
b[y] = x ;
ans = max(ans,x);
}
}
for(int i=1;i<=n;i++){
if(a[i] == 0){
int cnt = 1;
for(int j=0;j<v[i].size();j++){
if(a[v[i][j]] == 1){
cnt += b[find(v[i][j])];
}
}
ans = max(ans ,cnt);
}
}
printf("%d\n",ans);
return 0;
}