リンク:https
://ac.nowcoder.com/acm/contest/11334/J出典:Niuke.com
タイトルの説明
NiuNiuは、武道のスキルを練習するために一生懸命働きました-軽い水に浮かぶ、そして最終的に練習に失敗しました、しかし彼は木の上を歩く能力を学びました。
この日、ニウニウは敵の罠に陥りました。彼の後ろを追いかけている岩がありました。彼の前にn個のポイントがありました。n-1個のエッジが接続されて接続されたグラフ(ツリー)を形成しました。ニウニウはすぐにこのマップに入ることを選択する必要がありますが、ニウニウは見つけました。 、この写真には2つの異なるポイントがあります。ポイントを入力すると、そのポイントとは異なるすべてのポイントが消えます(接続されたエッジが消えます)、Niu Niuはエッジが接続されたポイントにのみ移動できます、NiuNiuは自分自身になりたいですできるだけ多くのポイントを獲得するようにしてください。そうすれば、彼はどのポイントに入ることができますか?
入力の説明:
最初の行には正の整数n {} nがあり、これはn {} n個のポイントがあることを意味します(n \ leq2×10 ^ 5)(n≤2×10
5
)
2番目の行にはn {} n個の番号a_iaがあります
iは点の二種類を表す(0 \のLeq a_iを\ 1当量1)(0≦A I ≦1)次のn-1 {}のn-1行毎に(V 2つの正の整数Uを有するU、 v \ leq n)u、v(u、v≤n)は、u {} uとv {} vの間にエッジがあることを意味します。出力の説明:出力の最初の行に入力できるポイントの数
2行目は、これらのポイントの数を小さいものから大きいものへと出力します。
実施例1
の入力
コピー
3
1 1 0
1 2
1 3
出力
コピー
2
1 2
説明
最大である、1及び2に落ちるときに2つの移動位置が存在することができる
(実施例2)
入力
コピー
4
1 1 0 0
1 2
2 3
3 4
出力
コピー
4
1 2 3 4
説明
、それが落ちるノー物、移動することができる2つの位置があります
2つのポイントが同じタイプの場合は、同じセットに入れます。最後に、最大のセットにあるポイントの数を確認し、最後に、最大のセットに等しいポイントの数を確認します。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 2e5 + 10;
int p[N], a[N], cnt[N];
int find(int x){
if (x != p[x]) p[x] = find(p[x]);
return p[x];
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i ++){
p[i] = i;
cnt[i] = 1;
}
for (int i = 1; i <= n; i ++){
scanf("%d", &a[i]);
}
for (int i = 1; i < n; i ++){
int x, y;
scanf("%d%d", &x, &y);
if (a[x] != a[y]) continue;
else{
int pa = find(x);
int pb = find(y);
// cout << "---------" << endl;
if (pa != pb){
p[pa] = pb;
cnt[pb] += cnt[pa];
}
}
}
int ans = 0;
int cnt1 = 0;
for (int i = 1; i <= n; i ++){
int p = find(i);
// cout << "----" << endl;
ans = max(cnt[p], ans);
}
vector<int> v;
for (int i = 1; i <= n; i ++){
int p = find(i);
if (cnt[p] == ans){
v.push_back(i);
}
}
cout << v.size() << endl;
for (int i = 0; i < v.size(); i ++){
cout << v[i] << " ";
}
cout << endl;
return 0;
}