農夫john準備把他的 n(1 <= n <= 10,000)頭牛排隊以便於行動。因為脾氣大的牛有可能會搗亂,john想把牛按脾氣的大小排序。每一頭牛的脾氣都是乙個在1到100,000之間的整數並且沒有兩頭牛的脾氣值相同。在排序過程中,john可以交換任意兩頭牛的位置。因為脾氣大的牛不好移動,john需要x+y秒來交換脾氣值為x和y的兩頭牛。
請幫john計算把所有牛排好序的最短時間。
第1行: 乙個數, n。第2~n+1行: 每行乙個數,第i+1行是第i頭牛的脾氣值。
第1行: 乙個數,把所有牛排好序的最短時間。示例1
複製
323複製1
7第一次接觸這個概念,一開始沒有什麼思路,後來看部落格才知道這個東西就是個置換問題。
題意:就是乙個亂序的排列通過兩兩置換來達到公升序,每次置換所需的**是兩點權值之和。
思路:首先理解乙個亂序排列存在迴圈節,也就是說其中一坨經過變換可以達到他們的公升序應該的位置,與其他的無關
例如公升序時: 1 2 3 4 5 6
亂序時: 4
6 3 1
25
如上所示,41為乙個迴圈節,256為乙個迴圈節,3為乙個迴圈節
那麼對於每乙個長度為n迴圈節的來說最優的策略就是用這n個數中的最小數來進行n-1次變換,
如上6 2 5 ,就是用2先和5換位置,變成6 5 2,再換2和6那麼就是2 5 6 正確的順序。
但是其實除了迴圈節自身進行n-1次置換,還有一種可能最優的策略就是拿乙個所有數中最小的數,與迴圈節裡邊的數進行n+1變換,具體自己理解上邊的例子 就是你可以用 1來對上邊的 6 2 5來變換
那麼這兩種花費分別為 迴圈節裡的最小的數*(迴圈節長度-1)+迴圈節裡其他數的和
最小的數*(迴圈節的長度+2)+迴圈節裡所有數之和
具體看**自己模擬理解:
#include#include#include#include#include#include#include#include#include#include#include#define myself i,l,r
#define lson i<<1
#define rson i<<1|1
#define lson i<<1,l,mid
#define rson i<<1|1,mid+1,r
#define half (l+r)/2
#define inff 0x3f3f3f3f
#define lowbit(x) x&(-x)
#define pi 3.14159265358979323846
#define min4(a,b,c,d) min(min(a,b),min(c,d))
#define min3(x,y,z) min(min(x,y),min(y,z))
#define pii make_pair
#define pr pairconst int dir[4][2]=;
typedef long long ll;
const ll inff=9223372036854775807;
typedef unsigned long long ull;
using namespace std;
const int maxn=1e4+5;
int c[maxn],vis[maxn];
int sum=0,minn=inff;
struct node
a[maxn];
bool cmp(node s,node e)
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++)
if(!vis[i]) sum+=dfs(i);
cout<}
bzoj1697 牛排序 置換群
ac通道 題解 將所給值離散之後,就是乙個置換群問題。初始狀態為離散值,目標狀態為1 n,交換這一行為映 置換,我們把這一置換迴圈分解而得到乙個置換群。對於群內的每個環,有乙個很貪心的辦法就是每次都讓權值最小的那個元素去和其他的元素交換,這樣交換的代價為sum min len 1 min 其中sum...
置換群的習題
題意 給定n,s n,sn,s和排列a1,a2 an a 1,a 2 dots,a n a1 a2 a n 若置換ps ap s a ps a 求置換ppp。考慮先找到排列a aa的迴圈節len lenle n,即a aa置換len s l en len s len len s len次能得到p p...
牛客團隊賽2 H 奶牛排序 (群置換)
奶牛排序 時間限制 c c 1秒,其他語言2秒 空間限制 c c 32768k,其他語言65536k 64bit io format lld 農夫john準備把他的 n 1 n 10,000 頭牛排隊以便於行動。因為脾氣大的牛有可能會搗亂,john想把牛按脾氣的大小排序。每一頭牛的脾氣都是乙個在1到...