# 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]

## Sample Input

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

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 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()
{
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\n",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];
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 {
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\n",ans);
48     return 0;
49 }
View Code

posted @ 2016-10-12 15:18  ACist  阅读(125)  评论(0编辑  收藏  举报