zoukankan      html  css  js  c++  java
  • BZOJ1119[POI2009]SLO && BZOJ1697[Usaco2007 Feb]Cow Sorting牛排序

    Problem J: [POI2009]SLO

    Time Limit: 30 Sec  Memory Limit: 162 MB
    Submit: 622  Solved: 302
    [Submit][Status][Discuss]

    Description

    对于一个1-N的排列(ai),每次你可以交换两个数ax与ay(x<>y),代价为W(ax)+W(ay) 若干次交换的代价为每次交换的代价之和。请问将(ai)变为(bi)所需的最小代价是多少。

    Input

    第一行N。第二行N个数表示wi。第三行N个数表示ai。第四行N个数表示bi。 2<=n<=1000000 100<=wi<=6500 1<=ai,bi<=n ai各不相等,bi各不相等 (ai)<>(bi) 样例中依次交换数字(2,5)(3,4)(1,5)

    Output

    一个数,最小代价。

    Sample Input

    6
    2400 2000 1200 2400 1600 4000
    1 4 5 3 6 2
    5 3 2 4 6 1

    Sample Output

    11200

    HINT

    题解:想到置换,发现在一个循环中,我们尽量让每个点与权值小的进行交换,但是这样会是最优吗?

       显然不是,我们忽略一种情况,我们可以将另一个循环中的一个最小的值与一个循环的一个节点交换,

       然后重复上述操作,再将它换回原来循环来产生更优的解!

       细节见代码:

    BZOJ1119

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #define ll long long 
    #define inf 0x7fffffff
    #define N 1000010
    using namespace std;
    int n;
    ll v[N],minn=inf,a[N],ans;
    int cnt[N];
    bool vis[N];
    ll read()
    {
        ll x=0,f=1; char ch;
        while (ch=getchar(),ch<'0'||ch>'9') if (ch=='-') f=-1;
        while (x=x*10+ch-'0',ch=getchar(),ch>='0'&&ch<='9');
        return x*f;
    }
    int main()
    {
        n=read();
        for (int i=1; i<=n; i++) v[i]=read(),minn=min(minn,v[i]);
        for (int i=1; i<=n; i++) a[i]=read();
        for (int i=1; i<=n; i++) cnt[read()]=i;
        for (int i=1; i<=n; i++)
        {
            if (!vis[i])
            {
                ll t=0,mn=inf,sum=0; int j=i;
                while (!vis[j])
                {
                    vis[j]=1; t++; sum+=v[a[j]]; mn=min(mn,v[a[j]]); j=cnt[a[j]]; 
                }
                if (t>=2)
                {
                    ll t1=sum+1ll*mn*(t-2),t2=sum+mn+1ll*minn*(t+1);
                    ans+=min(t1,t2); 
                }
            }
        } 
        printf("%lld
    ",ans);
        return 0;
    }
    View Code

    BZOJ1697

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<cstdio>
     6 #define ll long long 
     7 #define inf 0x7fffffff 
     8 #define N 100005
     9 using namespace std;
    10 struct point{
    11     ll v,pos;
    12 }tmp[N];
    13 ll v[N],minn=inf,a[N],ans;
    14 int cnt[N];
    15 bool vis[N];
    16 ll read()
    17 {
    18     ll x=0,f=1; char ch;
    19     while (ch=getchar(),ch<'0'||ch>'9') if (ch=='-') f=-1;
    20     while (x=x*10+ch-'0',ch=getchar(),ch>='0'&&ch<='9');
    21     return x*f;
    22 }
    23 bool cmp(point a,point b){return a.v<b.v;
    24 }
    25 int main()
    26 {
    27     int n=read();
    28     for (int i=1; i<=n; i++) v[i]=tmp[i].v=read(),a[i]=tmp[i].pos=i,minn=min(minn,tmp[i].v);
    29     sort(tmp+1,tmp+n+1,cmp);
    30     for (int i=1; i<=n; i++){cnt[tmp[i].pos]=i;}
    31     for (int i=1; i<=n; i++)
    32     {
    33         if (!vis[i])
    34         {
    35             ll t=0,mn=inf,sum=0; int j=i;
    36             while (!vis[j])
    37             {
    38                 vis[j]=1; t++; sum+=v[a[j]]; mn=min(mn,v[a[j]]); j=cnt[a[j]]; 
    39             }
    40             if (t>=2)
    41             {
    42                 ll t1=sum+1ll*mn*(t-2),t2=sum+mn+1ll*minn*(t+1);
    43                 ans+=min(t1,t2); 
    44             }
    45         }
    46     } 
    47     printf("%lld
    ",ans);
    48     return 0;
    49 }
    View Code
  • 相关阅读:
    12
    11-常用模块
    10-异常处理
    C#程序关闭时怎么关闭子线程
    [转]Android加载图片堆栈溢出
    [转]JS弹出确认/取消对话框
    [整理]获取当前页面的网址
    C/C++多参数处理
    图标素材网站收集
    PHP "Warning: Unknown: failed to open stream: Permission denied in Unknown on line 0" 错误
  • 原文地址:https://www.cnblogs.com/HQHQ/p/5952992.html
Copyright © 2011-2022 走看看