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
  • 相关阅读:
    那些离不开的 Chrome 扩展插件
    Spring Boot 实战 —— 入门
    Maven 学习笔记
    Linux lvm 分区知识笔记
    Linux 双向 SSH 免密登录
    CentOS Yum 源搭建
    Ubuntu 系统学习
    iOS 测试三方 KIF 的那些事
    Swift 网络请求数据与解析
    iOS Plist 文件的 增 删 改
  • 原文地址:https://www.cnblogs.com/HQHQ/p/5952992.html
Copyright © 2011-2022 走看看