挪酒瓶 牛客小白月赛33
考察:思维
看半天没看出来,还以为和求最短交换次数差不多...实际完全不一样.菜狗不配...
思路:
如果我们再交换a1和a4就可以化为更小的环.每步交换都是两个权值之和.因此假设a1是环中最小的,就由贪心得交换的最小权值和是4*w1+w2+w3+w4+w5
但是如果这样贪心交上去依然WA,下面的测试数据可以卡掉这种做法:
5 1 3 4 5 2 1 90 90 90 90
可以发现环中的再怎么交换都不如将1号酒瓶也换到环中的做法.所有最优解是每个环两者做法取最小值再累加.
1 #include <iostream> 2 #include <cstring> 3 #include <vector> 4 #include <set> 5 using namespace std; 6 const int N = 100010,INF = 0x3f3f3f3f; 7 int n,p[N],w[N],minv = INF; 8 bool st[N]; 9 int solve() 10 { 11 int res = 0; 12 for(int i=1;i<=n;i++) 13 if(p[i]!=i) 14 { 15 int sum = 0,cnt = 0,mins = INF; 16 if(st[i]) continue; 17 for(int k=i;!st[k];k = p[k]) 18 { 19 st[k] = 1; 20 sum+=w[k]; 21 cnt++; 22 mins = min(w[k],mins); 23 } 24 res += sum+min(minv*(cnt+1)+mins,mins*(cnt-2)); 25 } 26 return res; 27 } 28 int main() 29 { 30 int T; 31 scanf("%d",&T); 32 while(T--) 33 { 34 scanf("%d",&n); 35 minv = INF; 36 for(int i=1;i<=n;i++) scanf("%d",&p[i]); 37 for(int i=1;i<=n;i++) 38 { 39 scanf("%d",&w[i]); 40 st[i] = 0; 41 minv = min(minv,w[i]); 42 } 43 int res = solve(); 44 printf("%d\n",res); 45 } 46 return 0; 47 }