白魔法師(DFS&並查集)
思路:搜索每個白色連通塊,用數組紀錄每個白色連通塊的大小,
用數組記錄結點屬於那個白色連通塊。然後遍歷一遍結點,如果是白色,則直接取最大值,如果是黑色,則答案
時間複雜度:
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;
}