给你两个队列,a,b。a[i]代表第i个位置的串要放到第a[i]个位置。b[i]代表第i个位置的串去放的时候翻不翻面。
要让所有位置的串都正反在n个位置都烤一遍。
给你的队列可能不满足条件,让你更换队列里的一些数字,求最小变化数字的次数。
POINT:
即要让a队列变成一个环,b队列变成单数就行。
a怎么变成环:
把a[i]跑的路径都变成一条一条的。然后条数首位相连。变化次数就是条数。
注意如果a[i]只需跑一次,那么也要特判。判断他是否是真环,还是只是【单纯都走过了一遍】(即再次走的时候走不到某些点)。比如(6),看形状。
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <iostream>
#include <math.h>
#include <map>
using namespace std;
#define LL long long
const int maxn = 2e5+44;
int a[maxn];
int flag[maxn];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
int num=0;
for(int i=1;i<=n;i++){
int b;scanf("%d",&b);
if(b&1) num++;
}
int ans=0;
if(num%2==0) ans++;
num=0;
for(int i=1;i<=n;i++){
int now=i;
if(flag[now]==0) num++;
while(flag[now]==0){
flag[now]=1;
now=a[now];
}
}
int f[maxn];
memset(f,0,sizeof f);
if(num==1){
int now=1;
int p=0;
while(now){
now=a[now];
if(now==1){
printf("%d\n",ans);
return 0;
}
p++;
if(p>n+44) break;
}
}
printf("%d\n",ans+num);
return 0;
}