AcWing 1921. 重新排列奶牛
题意
可以选择任意头奶牛,将他们进行循环移位,给定移位前的顺序和移位后的顺序,请计算奶牛们完成重新排列,共需多少组循环移位,最长的一组循环移位的长度是多少。
示例:
移位前:5 1 4 2 3
移位后:2 5 3 1 4
如上例中,将 5,1,2 号奶牛分在一组进行循环移位,移动过后,5 号奶牛移动至位置 2,1 号奶牛移动至位置 4,2 号奶牛移动至位置 1;将 4,3 号奶牛分在另一组进行循环移位,移动过后,4 号奶牛位于位置 5,3 号奶牛位于位置 3;最终完成重新排列。
数据范围
\(1 \le N \le 100\)
\(1 \le A(i), B(i) \le N\)
题解
注意环的长度为1的情况,不仅需要排除自环,还要排除单个的点,注意ans1和ans2的计数。
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 110;
int a[N], b[N];
int e[N], ne[N], h[N], idx;
bool st[N];
int n;
void add(int a, int b){
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
int bfs(int x){
int res = 0;
queue<int> q;
q.push(x);
while(q.size()){
auto t = q.front();
q.pop();
//cout << t << ' ';
res ++;
for(int i = h[t]; i != -1; i = ne[i]){
int j = e[i];
if(st[j]) continue;
q.push(j);
st[j] = true;
}
}
//cout << '\n';
return res;
}
int main()
{
scanf("%d", &n);
for(int i = 0; i < n; i ++) scanf("%d", &a[i]);
for(int i = 0; i < n; i ++) scanf("%d", &b[i]);
memset(h, -1, sizeof h);
for(int i = 0; i < n; i ++) {
if(a[i] != b[i]) add(b[i], a[i]);
}
int ans1 = 0, ans2 = -1;
for(int i = 0; i < n; i ++){
if(!st[a[i]]){
st[a[i]] = true;
int t = bfs(a[i]);
if(t > 1) ans2 = max(ans2, t), ans1 ++;
}
}
printf("%d %d\n", ans1, ans2);
return 0;
}