白魔法师(DFS&并查集)
思路: d f s dfs dfs搜索每个白色连通块,用数组 s z [ i ] sz[i] sz[i]纪录每个白色连通块的大小,
用数组 b l [ i ] bl[i] bl[i]记录结点 i i i属于那个白色连通块。然后遍历一遍结点,如果是白色,则直接取最大值,如果是黑色,则答案 = 1 + ∑ 与 u 相 连 的 结 点 v s z [ v ] =1+\sum\limits_{与u相连的结点v}sz[v] =1+与u相连的结点v∑sz[v]
时间复杂度: O ( V + E ) O(V+E) O(V+E)
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =1e5+5;
vector<int>e[N];
char s[N];
int n,sz[N],bl[N],id;//bl[i] 第i个结点归属那个白色连通块belong,sz[i]表示第i个白色连通块的大小
void dfs(int u,int fa){
bl[u]=id;
sz[id]++;
for(auto v:e[u]){
if(v==fa||s[v]=='B') continue;
dfs(v,u);
}
}
int main(){
scanf("%d%s",&n,s+1);
for(int i=1,u,v;i<n;i++){
scanf("%d%d",&u,&v);
e[u].push_back(v);
e[v].push_back(u);
}
for(int i=1;i<=n;i++) if(s[i]=='W'&&!bl[i]) id++,dfs(i,0);//搜索每个白色连通块
int ans=0;
for(int i=1;i<=n;i++){
if(bl[i]) ans=max(ans,sz[bl[i]]);
else {//如果是黑色则加上它相连的白色连通块。
int res=1;
for(auto v:e[i]){
if(s[v]=='W') res+=sz[bl[v]];
}
ans=max(ans,res);
}
}
printf("%d\n",ans);
return 0;
}
并查集做法:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =1e5+5;
vector<int>e[N];
char s[N];
int n,fa[N],sz[N],ans;
int find(int x){
if(x!=fa[x]) fa[x]=find(fa[x]);
return fa[x];
}
int main(){
scanf("%d%s",&n,s+1);
for(int i=1;i<=n;i++) fa[i]=i,sz[i]=1;//初始化
for(int i=1,u,v;i<n;i++){
scanf("%d%d",&u,&v);
e[u].push_back(v);
e[v].push_back(u);
if(s[u]==s[v]&&s[u]=='W'){//合并白色连通块
u=find(u),v=find(v);
if(u!=v) fa[u]=v,sz[v]+=sz[u];
}
}
for(int i=1;i<=n;i++){
if(s[i]=='W') ans=max(ans,sz[find(i)]);//注意sz 里的结点是白色连通块的根
else {
int res=1;
for(auto v:e[i]){
if(s[v]=='W') res+=sz[find(v)];
}
ans=max(res,ans);
}
}
printf("%d\n",ans);
return 0;
}