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;最终完成重新排列。

数据范围

1N100
1A(i),B(i)N

题解

image

注意环的长度为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;
}
posted @   小菜珠的成长之路  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
点击右上角即可分享
微信分享提示