zoukankan      html  css  js  c++  java
  • 洛谷 P2127 序列排序

    https://www.luogu.org/problemnew/show/P2127

    感觉题解里写的比较复杂,可能自己的想法比较简单一点吧。

    看这个图中的的点如果形成一个环,贪心的考虑,要想花费最少,那么我们一定要多次利用最小那个点。

    图中来看就是2和6交换,然后2和4交换,然后就交换完了。

    然而还有一种换法就是,这个环中最小的点和序列中最小的点先交换,然后在进行环内的操作(就是说先2和1交换...)。

    所以对于每个点dfs找到环,然后判断两种方法哪种更优,统计答案。

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    #define LL long long
    #define inf 2147483647
    LL n,a[100006],b[100006],MIN,pos[100006],siz,sum,minn;
    bool vis[100006];
    LL ans;
    void dfs(int x)
    {
        if(vis[x])return ;
        sum+=a[x];    //记录环内每个点的总和 
        siz++;        //环内有多少个点 
        MIN=min(MIN,a[x]);    //环内最小值 
        vis[x]=1;    //打上标记 
        dfs(pos[x]);    //下一个点 
    }
    int main()
    {
        scanf("%d",&n);
        minn=MIN=inf;
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
            b[i]=a[i];
            minn=min(minn,a[i]);    //记录序列最小值 
        }
        sort(b+1,b+1+n);    //排序 
        for(int i=1;i<=n;i++)
            pos[i]=lower_bound(b+1,b+1+n,a[i])-b;    //记录排序后的位置 
        for(int i=1;i<=n;i++)
        {
            if(!vis[i])
            {
                dfs(i);
                ans+=min(sum+MIN+minn*(siz+1),sum+MIN*(siz-2));
    /*
            方法一:交换序列最小值和环内最小值 + 序列最小值 * 环内点数 
            方法二:环内最小值*环内点数。 
    */ 
                siz=0; sum=0; MIN=inf;
            }
        }
        printf("%lld",ans);
    }
  • 相关阅读:
    RecyclerView-------MainActivity代码
    ListView控件
    Java 内部类的阐述
    JAVA匿名内部类
    Process.Start(@"C:WindowsSystem32osk.exe") 找不到指定文件
    The program can't start because AppVIsvSubsystems64.dll is missing from your computer
    Rclone webapi 使用例子
    C# lock 死锁问题排查方法
    zeroc ICE 使用案例
    log4net 纯代码配置
  • 原文地址:https://www.cnblogs.com/rmy020718/p/9776065.html
Copyright © 2011-2022 走看看