Round Dance
题意:
现在有n个人,每个人记得一个邻居,每个人可以找两个人跳舞,跳舞最少要两个人,每个人都要跳舞,首先他要去找他记得的邻居a[i],然后还可以再选一个人连起来。问最少和最多可以有多少组舞蹈。
思路:
首先用并查集将a[i]和i连起来,然后每个联通块都是一组舞蹈,最多数量就是联通块的数量,因为每个人可以找两个人组合,所以环是无法再拉入人的,因为每个人都有两条边,而当一个联通块里面有链,它就可以与其他的包含链的联通块组合起来。所以最小数量就是成环的联通块,如果有存在链的联通块,就再加一,因为链可以合并起来。至于找链,只要a[a[i]] == i,那么这个联通块里面就有链,因为一个环的话每个人都会和两个不同的人连边,如果存在两个人连了两条边,就一定不存在环。
代码
int n, a[maxn];
int p[maxn];
int find(int x) {
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
void merge(int x, int y) {
if (find(x) == find(y)) return;
p[find(x)] = find(y);
}
void solve() {
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= n; i++) p[i] = i;
for (int i = 1; i <= n; i++)
merge(i, a[i]);
int mi = 0, mx = 0;
int chain = 0;
vector<int> e(n + 1, 0);
for(int i = 1; i <= n; i ++ )
if (a[a[i]] == i) {
e[find(i)] = 1;
chain = 1;
}
for (int i = 1; i <= n; i++) {
if (find(i) == i) {
if (!e[i]) mi++;
mx++;
}
}
cout << mi + chain << ' ' << mx << endl;
}