bzoj1697:[Usaco2007 Feb]Cow Sorting牛排序 & bzoj1119:[POI2009]SLO

思路:以bzoj1119为例,题目已经给出了置换,而每一次交换的代价是交换二者的权值之和,而置换一定是会产生一些环的,这样就可以只用环内某一个元素去置换而使得其余所有元素均在正确的位置上,显然要选择环内最小的数,但也可能存在一个数使得它不在当前处理的环内而它先与当前环内某个数进行交换,然后再在环内进行交换,再将之前那个数换回来,这样也显然要选择所有元素中最小的和当前环内最小的进行交换,然后取个min即可。然后还要注意可能当前环内最小的就是所有元素中最小的,特判一下即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 #define maxn 1000100
 8 #define inf 1e9
 9
10 int n,minval=inf,tot;
11 long long ans;
12 int a[maxn],pos[maxn],b[maxn],val[maxn],next[maxn];
13 bool vis[maxn];
14
15 int read(){
16     int x=0,f=1;char ch=getchar();
17     for (;ch<‘0‘||ch>‘9‘;ch=getchar()) if (ch==‘-‘) f=-1;
18     for (;ch>=‘0‘ && ch<=‘9‘;ch=getchar()) x=x*10+ch-‘0‘;
19     return x*f;
20 }
21
22 int main(){
23     n=read();
24     for (int i=1;i<=n;i++) val[i]=read(),minval=min(minval,val[i]);
25     for (int i=1;i<=n;i++) a[i]=read(),pos[a[i]]=i;
26     for (int i=1;i<=n;i++) b[i]=read(),next[pos[a[i]]]=pos[b[i]];
27     for (int i=1;i<=n;i++)
28         if (!vis[i]){
29             long long sum=0;int size=0,v=inf;
30             while (!vis[i]) vis[i]=1,size++,sum+=val[a[i]],v=min(v,val[a[i]]),i=next[i];
31             if (size<=1) continue;
32             long long ans1=sum-v+1ll*v*(size-1),ans2=sum+v+1ll*minval*(size+1);
33             if (v!=minval) ans+=min(ans1,ans2);else ans+=ans1;
34         }
35     printf("%lld\n",ans);
36 } 

bzoj1119

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 #define maxn 100100
 8 #define inf 1e9
 9
10 int n,minval=inf,ans;
11 int tmp[maxn],val[maxn],pos[maxn],next[maxn];
12 bool vis[maxn];
13
14 int read(){
15     int x=0,f=1;char ch=getchar();
16     for(;ch<‘0‘ || ch>‘9‘;ch=getchar())if (ch==‘-‘) f=-1;
17     for(;ch>=‘0‘ && ch<=‘9‘;ch=getchar()) x=x*10+ch-‘0‘;
18     return x*f;
19 }
20
21 int main(){
22     n=read();
23     for (int i=1;i<=n;i++) tmp[i]=val[i]=read(),pos[val[i]]=i,minval=min(minval,val[i]);
24     sort(tmp+1,tmp+n+1);
25     for (int i=1;i<=n;i++) next[pos[tmp[i]]]=pos[val[i]];
26     for (int i=1;i<=n;i++){
27         int sum=0,size=0,v=inf;
28         while (!vis[i]) vis[i]=1,size++,sum+=val[i],v=min(v,val[i]),i=next[i];
29         if (size<=1) continue;
30         int ans1=sum+v*(size-2),ans2=sum+minval*(size+1)+v;
31         if (minval!=v) ans+=min(ans1,ans2);else ans+=ans1;
32     }
33     printf("%d\n",ans);
34     return 0;
35 }

bzoj1697

时间: 2024-12-19 19:39:18

bzoj1697:[Usaco2007 Feb]Cow Sorting牛排序 & bzoj1119:[POI2009]SLO的相关文章

[BZOJ1697][Usaco2007 Feb]Cow Sorting牛排序

1697: [Usaco2007 Feb]Cow Sorting牛排序 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 712  Solved: 416 [Submit][Status][Discuss] Description 农夫JOHN准备把他的 N(1 <= N <= 10,000)头牛排队以便于行动.因为脾气大的牛有可能会捣乱,JOHN想把牛按脾气的大小排序.每一头牛的脾气都是一个在1到100,000之间的整数并且没有两头牛的脾气值相同.

bzoj 1697: [Usaco2007 Feb]Cow Sorting牛排序

Description 农夫JOHN准备把他的 N(1 <= N <= 10,000)头牛排队以便于行动.因为脾气大的牛有可能会捣乱,JOHN想把牛按脾气的大小排序.每一头牛的脾气都是一个在1到100,000之间的整数并且没有两头牛的脾气值相同.在排序过程中,JOHN 可以交换任意两头牛的位置.因为脾气大的牛不好移动,JOHN需要X+Y秒来交换脾气值为X和Y的两头牛. 请帮JOHN计算把所有牛排好序的最短时间. Input 第1行: 一个数, N. 第2~N+1行: 每行一个数,第i+1行是第

【BZOJ】1697: [Usaco2007 Feb]Cow Sorting牛排序

[算法]数学置换 [题意]给定n个数,要求通过若干次交换两个数的操作得到排序后的状态,每次交换代价为两数之和,求最小代价. [题解] 考虑置换的定义:置换就是把n个数做一个全排列. 从原数组到排序数组的映射就是经典的置换,这样的置换一定能分解成循环的乘积. 为什么任意置换都可以这样分解:原数组的每个数要交换到排序位置(有后继),每个数的原位置会有数字来替代(有前驱),故一定构成若干循环节. 循环节内要完成置换,需要按顺序依次替换位置进行len-1次对换(len为循环节长度). 对于每一循环节内部

P1697: [Usaco2007 Feb]Cow Sorting牛排序

这是一道置换群的裸题=-=,先拿来试试手对着打,以后应该会更加熟练吧! 1 const maxn=100001; 2 var n,i,j,maxx,minx,now,len,cursum,tmin,sum:longint; 3 p:array[0..maxn] of boolean; 4 agr,pos:array[0..maxn] of longint; 5 function min(a,b:longint):longint; 6 begin 7 if a>b then exit(b) 8 e

bzoj 1697: [Usaco2007 Feb]Cow Sorting牛排序【置换群】

至今都不知道置换群是个什么东西--题解说什么就是什么.jpg 以下来自hzwer:http://hzwer.com/3905.html #include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int N=10005; int n,w[N],a[N],v[N]; struct qwe { int x,id; }b[N]; bool cmp(const qwe &a

[BZOJ] 1631: [Usaco2007 Feb]Cow Party

1631: [Usaco2007 Feb]Cow Party Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 866  Solved: 624[Submit][Status][Discuss] Description 农场有N(1≤N≤1000)个牛棚,每个牛棚都有1只奶牛要参加在X牛棚举行的奶牛派对.共有M(1≤M≤100000)条单向路连接着牛棚,第i条踣需要Ti的时间来通过.牛们都很懒,所以不管是前去X牛棚参加派对还是返回住所,她们都采用了用时最

BZOJ 1631: [Usaco2007 Feb]Cow Party( 最短路 )

这道题和蔡大神出的今年STOI初中组的第二题几乎一模一样... 先跑一遍最短路 , 再把所有边反向 , 再跑一遍 , 所有点两次相加的最大值即为answer ----------------------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<cstring> #include<queue> #in

BZOJ1119: [POI2009]SLO

1119: [POI2009]SLO Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 379  Solved: 181[Submit][Status] Description 对于一个1-N的排列(ai),每次你可以交换两个数ax与ay(x<>y),代价为W(ax)+W(ay) 若干次交换的代价为每次交换的代价之和.请问将(ai)变为(bi)所需的最小代价是多少. Input 第一行N. 第二行N个数表示wi. 第三行N个数表示ai. 第四行N个

【BZOJ】1631: [Usaco2007 Feb]Cow Party(dijskstra)

http://www.lydsy.com/JudgeOnline/problem.php?id=1631 看到m<=100000果断用spfa(可是好像dij比spfa还慢了在这里?) #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> #include &