白魔法師(DFS&並查集)

白魔法師(DFS&並查集)

傳送門

思路:dfsdfs搜索每個白色連通塊,用數組sz[i]sz[i]紀錄每個白色連通塊的大小,

用數組bl[i]bl[i]記錄結點ii屬於那個白色連通塊。然後遍歷一遍結點,如果是白色,則直接取最大值,如果是黑色,則答案=1+uvsz[v]=1+\sum\limits_{與u相連的結點v}sz[v]

時間複雜度: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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章