• 洛谷1053 篝火晚会


    洛谷1053 篝火晚会


    原题链接


    交题记录

    20:28 30'
    数组开小了我还能说啥。。。还是WA,这lg。。。
    20:30 90'
    原因是忘记了序列可以反转。
    20:49 AC


    题解

    首先是有无解的问题。
    考虑极端,佳佳每次都可以交换两个人,只是代价大了点。所以只要关系构成环,就一定有解。
    这个dfs搞定
    dfs顺便计算出可行的序列。这个序列和它反过来的序列都可行(被坑了)。
    因为是环,所以断环为链,(O(n))枚举。
    两个序列(1,2,...,n)(s_1,s_2,...,s_n)最少总代价就是(sum_{i=1}^{n}s_i!=i)。可以一次命令把它们全部归位。
    到这里,算法复杂度为(O(n^2))
    再优化一下:(s_i!=i)的情况会出现n-1次,相反(s_i=i)只出现1次。记一个K数组,表示第i条链s_i=i出现的次数。答案就是(max(n-k[i]))
    注意序列可以反转。


    Code

    // It is made by XZZ
    #include<cstdio>
    #include<algorithm>
    #include<cstdlib>
    using namespace std;
    #define rep(a,b,c) for(rg int a=b;a<=c;a++)
    #define drep(a,b,c) for(rg int a=b;a>=c;a--)
    #define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
    #define il inline
    #define rg register
    #define lb(o) (o&-o)
    #define vd void
    typedef long long ll;
    il int gi(){
        rg int x=0,f=1;rg char ch=getchar();
        while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    const int maxn=50010;
    int a[maxn],b[maxn],s[maxn],tot,n,k[maxn],K[maxn];
    il vd dfs(int now,int lst){
        s[++tot]=now;
        if(tot==n)return;
        if(a[now]==lst)dfs(b[now],now);
        else if(b[now]==lst)dfs(a[now],now);
        else {puts("-1");exit(0);}
    }
    int main(){
        n=gi();
        rep(i,1,n)a[i]=gi(),b[i]=gi();
        dfs(1,a[1]);
        rep(i,1,n)++k[(s[i]-i+n)%n],++K[(s[i]+i+n)%n];
        int ans=1e9;
        rep(i,0,n-1)ans=min(ans,n-max(k[i],K[i]));
        printf("%d
    ",ans);
        return 0;
    }
    
    博主是蒟蒻,有问题请指出,谢谢!
    本博客中博文均为原创,未经博主允许请勿随意转载,谢谢。
  • 相关阅读:
    sublime使用
    eclipse导入工程中文乱码
    npm 代理
    栈和堆
    Linux常用命令大全
    Google云开启SSH登录方法
    景安快运挂在磁盘-支持宝塔
    discuz 批量删除回复并且保留主题的方法,亲测3.4版本通过
    博客园去掉页面的广告的方法
    WordPress忘记后台登录地址时怎么办?万能登录地址
  • 原文地址:https://www.cnblogs.com/xzz_233/p/7436371.html
Copyright © 2020-2023  润新知