用 BFS 加并查集的办法来维护每个可以连通的区块来找到节点最多的连通块即可
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const ll N=2e5+5;
vector<vector<ll>>adj(N);
bool vis[N];
ll cmp=1;
struct UF{
ll rank=0;
UF* root;
ll cnt=1;
bool p;
};
UF a[N];
UF* Root(UF* a){
if(a->root!=a){
a->root=Root(a->root);
}
return a->root;
}
void merge(UF* rx,UF*ry){
if(rx==ry)return;
if(rx->rank<ry->rank){
rx->root=ry;
ry->cnt+=rx->cnt;
cmp=max(ry->cnt,cmp);
}else{
ry->root=rx;
rx->cnt+=ry->cnt;
cmp=max(rx->cnt,cmp);
if(rx->rank==ry->rank){
rx->rank++;
}
}
}
void bfs(ll x){
queue<ll>q;
q.push(x);
while(!q.empty()){
ll t=q.front();
q.pop();
for(auto it:adj[t]){
if(vis[it]==0&&a[t].p==a[it].p){
merge(Root(&a[t]),Root(&a[it]));
vis[it]=1;
q.push(it);
}
}
}
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
ll n;
cin>>n;
for(ll i=1;i<=n;i++){
cin>>a[i].p;
a[i].root=&a[i];
}
for(ll i=1;i<=n-1;i++){
ll u,v;
cin>>u>>v;
adj[u].push_back(v);
adj[v].push_back(u);
}
for(ll i=1;i<=n;i++){
if(vis[i]==0){
vis[i]=1;
bfs(i);
}
}
vector<ll>ans;
for(ll i=1;i<=n;i++){
if(cmp==Root(&a[i])->cnt){
ans.push_back(i);
}
}
cout<<ans.size()<<'\n';
bool f=0;
for(auto t:ans){
if(f==0){
cout<<t;
f=1;
}else cout<<' '<<t;
}
return 0;
}

京公网安备 11010502036488号