这题是一个经典的环图模型。
y总说环图要补进提高课了!好开森~
我们先来看一下环图的定义:
给定一张图,如果这张图的每一个节点只有一条入边和一条出边,那么这一张图一定是由若干个环构成的,环不会出现交叉的情况,否则就会与上面的定义矛盾。这张图如果满足这些条件,那就叫环图。
环图分为有向和无向两种。
无向的环图可以理解为一个个集合。然而这题中的环图是有向的,怎么办?
没事,因为在一个环里,它边的指向并不重要,可以看作无向边,所以这题中的环图可以看作无向环图,用并查集解决。
那么就是一个简单的并查集处理了!
#include <bits/stdc++.h>
using namespace std;
int n, a[110], b[110], f[110], s[110], cnt, ans;
int get(int x) {
if (f[x] != x) return get(f[x]);
return f[x];
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
for (int i = 1; i <= n; i++) f[i] = i, s[i] = 1;
for (int i = 1; i <= n; i++) {
int x; cin >> x;
b[x] = i;
}
for (int i = 1; i <= n; i++) {
int x = a[i], y = a[b[x]];
if (get(x) != get(y)) {
s[get(y)] += s[get(x)];
f[get(x)] = get(y);
}
}
for (int i = 1; i <= n; i++) {
if (f[i] == i && s[i] > 1) //只拿长度大于1的环
cnt++, ans = max(ans, s[i]);
}
if (!cnt) ans = -1;
printf("%d %d", cnt, ans);
return 0;
}
对对对,和初始化 b 数组有关