1. 程式人生 > 其它 >AcWing 1921. 重新排列奶牛

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;
}