全部评论 3

  • #include<bits/stdc++.h>
    using namespace std;
    #define MAXN 50000+10
    int a[MAXN],b[MAXN],circle[MAXN],spin[MAXN];
     
    inline int read()//读入优化 不用写 
    {
        char ch='*';
        while(!isdigit(ch=getchar()));
        int num=ch-'0';
        while(isdigit(ch=getchar()))num=num*10+ch-'0';
        return num;
    }
    int main()
    {
        int n;
        n=read();
        for(int i=1;i<=n;i++)
        {    
            a[i]=read();b[i]=read();
        }
        circle[1]=1;
        circle[2]=a[1];//第一个点默认切环点
        for(int i=1;i<=n;i++)
        {
            if(b[a[i]]!=i&&a[a[i]]!=i||a[b[i]]!=i&&b[b[i]]!=i)//判断是否可行,由于是个圈,可逆,所以两次判定 
            {
                printf("-1");
                return 0;
            }
            //if(i>1)
                if(a[circle[i]]==circle[i-1])circle[i+1]=b[circle[i]];    //由于你并不知道这两个同学的左右,所以判断一下,免得建环重复一个点
                else circle[i+1]=a[circle[i]]; 
        }
        int ans=n+10;//最多n-1,n+10没问题了 
        for(int i=1;i<=n;i++)//这里开始是重点,就是找旋转次数,本蒟蒻一开始一直没理解,找大佬讲了好久才懂,如果旋转次相同,就可以看作与序列匹配,即为不用换位置的个数 
        {
            spin[((i-circle[i]+n))%n]++;//直接膜就可以,+n把负数改过来,最后移动步数为0~n-1;
            ans=min(ans,n-spin[((i-circle[i]+n))%n]);//答案是否需要更新 
        }
        memset(spin,0,sizeof(spin));//重新初始化,准备反跑 
        memset(circle,0,sizeof(circle));
        circle[0]=1;
        circle[1]=b[1];
        for(int i=1;i<=n;i++)
        {
            if(b[circle[i]]==circle[i-1])circle[i+1]=a[circle[i]];
            else circle[i+1]=b[circle[i]];//反跑直接反过来,ctrl+c&&ctrl+v 
        }
        for(int i=1;i<=n;i++) 
        {
            spin[((i-circle[i]+n))%n]++;
            ans=min(ans,n-spin[((i-circle[i]+n))%n]);//反跑反正数组不会变,一样的ctrl+c&&ctrl+v
        }
        printf("%d",ans);
    }
    

    3天前 来自 北京

    1
  • RE了

    3天前 来自 北京

    0
  • 不让用1e7好像是因为由于精度丢失还是啥的所以1e7直接填会成为一个浮点数,不可能有小数个下标吧(

    2024-09-03 来自 安徽

    0
首页