核心思路:你一进某个点,就只会保留和它同类型的点,所以你最终能活动的范围,其实就是“同类型点构成的子图里,你所在连通块的大小”。

做法很直接:在原树上按类型分开跑连通块(0 和 1 各自连),算出每个点所属连通块大小,取最大值,把所有块大小等于最大值的点输出即可。

void solve(){
    int n;cin>>n;
    vi a(n+1);
    for(int i=1;i<=n;++i){
        cin>>a[i];
    }
    vvi g(n+1);
    for(int i=1;i<=n-1;++i){
        int u,v;cin>>u>>v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    vi vis(n+1,0),sz(n+1,0);
    for(int i=1;i<=n;++i){
        if(vis[i]){
            continue;
        }
        vi st,comp;
        st.push_back(i);
        vis[i]=1;
        while(!st.empty()){
            int u=st.back();
            st.pop_back();
            comp.push_back(u);
            for(int j=0;j<(int)g[u].size();++j){
                int v=g[u][j];
                if(vis[v]||a[v]!=a[u]){
                    continue;
                }
                vis[v]=1;
                st.push_back(v);
            }
        }
        int cnt=(int)comp.size();
        for(int j=0;j<cnt;++j){
            sz[comp[j]]=cnt;
        }
    }
    int mx=0;
    for(int i=1;i<=n;++i){
        if(sz[i]>mx){
            mx=sz[i];
        }
    }
    vi ans;
    for(int i=1;i<=n;++i){
        if(sz[i]==mx){
            ans.push_back(i);
        }
    }
    cout<<ans.size()<<endl;
    for(int i=0;i<(int)ans.size();++i){
        cout<<ans[i]<<" ";
    }
    cout<<endl;
}