1. 程式人生 > >51nod 1125 交換機器的最小代價

51nod 1125 交換機器的最小代價

esp 依次 mat names 其他 51nod n) max 整數

基準時間限制:1 秒 空間限制:131072 KB

有N臺機器重量各不相等,現在要求把這些機器按照重量排序,重量從左到右依次遞增。移動機器只能做交換操作,但交換機器要花費一定的費用,費用的大小就是交換機器重量的和。例如:3 2 1,交換1 3後為遞增排序,總的交換代價為4。給出N臺機器的重量,求將所有機器變為有序的最小代價。(機器的重量均為正整數) Input
第1行:1個數N,表示機器及房間的數量。(2 <= N <= 50000)
第2 - N + 1行:每行1個數,表示機器的重量Wi。(1 <= Wi <= 10^9)
Output
輸出最小代價。
Input示例
3
3
2
1
Output示例
4


題解:

  一個非常神奇的貪心題目。

  首先,我們先考慮模型轉化一下,考慮轉化成一個圖論問題,將每個位置看成一個節點,初始狀態下,向位於這個節點的機器,想去的節點連邊。因為每個節點只有一個想去的地方,也只有一個機器想去他,所以每個節點的出入度都為一,那麽這個圖就顯然是由若幹環組成的。

  對於每個環,我們考慮交換的策略,顯然每個機器至少被交換一次,如果順這圖走,只要走一次就可以走到目標節點。但總是有機器要後退得走,離目標越來越遠,反著走遍整個環才可以到達目標,為了保證最優,那麽我們肯定選擇重量最小的機器反著遍歷整個環。然後其他點就跟這個反著遍歷的機器,交換一次就可以達到目標節點。

  但還有一種最優策略,就是從別的環裏面,把所有點中最小的點來換當前環最小的節點,然後再用這個最小點來遍歷整個環,因為兩種策略都有可能,所有要取min。

代碼:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
#define MAXN 50100
#define ll long long
using namespace std;
struct
node{ int id,w; }a[MAXN]; int n,minn; ll ans=0; bool b[MAXN]; bool cmp(node x,node y){ return x.w<y.w; } ll dfs(int aum){ ll sz=1,tot=a[aum].w,Min=a[aum].w,now=a[aum].id; b[aum]=1; while(now!=aum){ b[now]=1; sz++; Min=min(Min,(ll)a[now].w); tot+=a[now].w; now=a[now].id; } return min((sz-1)*Min+tot-Min,(sz+1)*minn+tot+Min); } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i].w),a[i].id=i; sort(a+1,a+n+1,cmp); minn=a[1].w; for(int i=1;i<=n;i++) if(!b[i]) ans+=dfs(i); printf("%lld",ans); return 0; }

51nod 1125 交換機器的最小代價