Minimum Üçlük#12307

Minimum Üçlük (Həll təhlili)

Problem Müəllifi:

Hasan Saleh (MathModel)

Hazırlayan:

Hasan Saleh (MathModel)

Redaktə edən:

Hasan Saleh (MathModel)

Həll

Bizə bir permutasiya verilir və bir hərəkətdə i<j<k indeksləri üzərində -lü dövr tətbiq edə bilərik:

(p_i,p_j,p_k)\leftarrow(p_j,p_k,p_i) \quad\text{və ya}\quad (p_i,p_j,p_k)\leftarrow(p_k,p_i,p_j).

Məqsədimiz minimum sayda hərəkət edərək identiklik permutasiyasına çatmaqdır.

Qeyd edin ki, -lü dövr cüt permutasiya olduğundan

(a\,b\,c)=(a\,c)(a\,b).

Beləliklə, permutasiya pariteti heç vaxt dəyişmir.

Permutasiyanın ayrılmış dövrə (sabit nöqtələr daxil olmaqla) ayrıldığını düşünək. Biz bilirik ki,

\operatorname{sgn}(p)=(-1)^{n-c}.

Beləliklə, əgər (n-c) təkdirsə, permutasiya təkdir və identikliyin əldə edilməsi mümkün deyil. Bu halda cavab -dir.

İndi (n-c) cütdürsə, fərz edək.

Hər dövrü müstəqil şəkildə işləyə bilərik, buna görə də bir dövrün uzunluğu olan dövrü pozmaq üçün nə qədər əməliyyat lazım olduğunu anlamaq kifayətdir.

Bir -lü dövr əməliyyatı dövrlərin sayını ən çox artırır. Bir uzunluğu olan dövrü sabit nöqtəyə çevirmək üçün dövrlərin sayını (l-1) artırmalıyıq, buna görə də hərəkətlərin sayı ən azı

\left\lceil \frac{l-1}{2} \right\rceil = \left\lfloor \frac{l}{2} \right\rfloor.

İndi bu sərhədin əldə oluna biləcəyini göstəririk.

  • Əgər təkdirsə, dövr özü cütdür. Biz yalnız bu dövrün elementlərindən istifadə edə bilərik və hər əməliyyat dövrlərin sayını artırır. (l-1)/2 hərəkətdən sonra dövr tamamilə sabitləşir.

  • Əgər cütdürsə, dövr təkdir və tək başına sabitləşdirilə bilmir. Lakin, (n-c) cütdürsə, cüt uzunluqda başqa bir dövr (və ya əlavə elementlər) mövcuddur. Bunu istifadə edərək, dövr hələ də tam olaraq əməliyyatla sabitləşdirilə bilər.

Beləliklə, uzunluğu olan bir dövr dəqiq

\left\lfloor \frac{l}{2} \right\rfloor

hərəkət edir.

Uzunluqları l_1,l_2,\dots,l_c olan bütün dövrləri topladıqda, biz alırıq:

\text{cavab} = \sum_{i=1}^{c} \left\lfloor \frac{l_i}{2} \right\rfloor.

Əgər (n-c) təkdirsə, çıxarın, əks halda yuxarıdakı dəyəri çıxarın.

Mürəkkəblik .

for _ in range(int(input())):
    n=int(input())
    p=[0]+list(map(int,input().split()))
    vis=[0]*(n+1)
    ans=0
    c=0
    for i in range(1,n+1):
        if vis[i]: continue
        c+=1
        cur=i
        l=0
        while not vis[cur]:
            vis[cur]=1
            cur=p[cur]
            l+=1
        ans+=l//2
    print(-1 if ((n-c)&1) else ans)