NC220558. 挪酒瓶
描述
输入描述
第一行一个正整数,代表测试数据的组数
每组测试数据有3行,第一行一个正整数,表示酒瓶的数量
第二行个正整数
,表示第
个酒瓶想要到
位置上。输入保证
到
在
中恰出现一次。
第三行个正整数
,表示第
瓶酒的重量为
输出描述
每组输入数据输出一行,代表花费
示例1
输入:
2 4 2 1 4 3 10 20 30 40 3 2 3 1 10 20 30
输出:
100 70
Python3(3.9) 解法, 执行用时: 1765ms, 内存消耗: 31856K, 提交时间: 2021-04-23 13:29:30
T = int(input()) while T: T -= 1 ans = 0 N = int(input()) p = list(map(int,input().split(' '))) for i in range(N): p[i] -= 1 w = list(map(int,input().split(' '))) allmin = min(w) vis = [0] * N for i in range(N): if vis[i] == 0: j = i cnt = 0 sumnow = 0 nowMin = float('inf') while vis[j] == 0: vis[j] = 1 cnt += 1 sumnow += w[j] nowMin = min(nowMin,w[j]) j = p[j] ans += min(sumnow + (cnt - 2) * nowMin, sumnow + nowMin + (cnt + 1) * allmin) print(ans)
C++(clang++11) 解法, 执行用时: 208ms, 内存消耗: 1072K, 提交时间: 2021-04-10 19:47:45
#include <stdio.h> #include <algorithm> #include <vector> #define MN 100000 int n,a[MN+5],w[MN+5]; void solve(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) scanf("%d",&w[i]); int ans = 0; int minw = 233; for(int i=1;i<=n;i++) minw = std::min(minw,w[i]); for(int i=1;i<=n;i++){ if(!w[i]) continue; int p = i; int tot = 0; int lminw = 233; int cnt = 0; do{ tot += w[p]; lminw = std::min(lminw,w[p]); w[p] = 0; cnt++; p = a[p]; }while(p!=i); ans += std::min((cnt-2)*lminw+tot,minw*(cnt+1)+tot+lminw); } printf("%d\n",ans); } int main(){ int T; scanf("%d",&T); while(T--) solve(); }