思路:利用并查集将会出现在同一个房间的下标统一化
在深度遍历中寻找同一房间的下标们消耗最小值
若是在老鼠跳转中出现a[i]=i,则连同同一房间的老鼠们都会去i房间
若是出现回环,则比较回环中的最小值
1 typedef long long ll; 2 typedef pair<int, int> p; 3 typedef unsigned long long ull; 4 int n; 5 int c[200005]; 6 int a[200005]; 7 int v[200005]; 8 int visited[200005]; 9 int fa[200005], rankv[200005]; 10 int fin(int v) { 11 return fa[v] = fa[v] == v ? v : fin(fa[v]); 12 } 13 14 ll ans = 0; 15 int dfs(int ind, int minc = 200000) { //遍历找到最后的顶点 16 v[ind]++; 17 // a[i]=i时或者出现a数组出现环时循环找出最小值 18 if (v[ind] >= 3) { 19 // cout << v[ind] << endl; 20 ans += minc; 21 return 1; 22 } 23 if (v[ind] == 2) { 24 // cout << v[ind] << endl; 25 dfs(a[ind], min(minc, c[ind])); 26 } 27 else { 28 // cout << v[ind] << endl; 29 dfs(a[ind], minc); 30 } 31 return 0; 32 } 33 34 int main() { 35 cin >> n; 36 for (int i = 1; i <= n; i++) { 37 fa[i] = i; 38 rankv[i] = 0; 39 } 40 for (int i = 1; i <= n; i++) { 41 cin >> c[i]; 42 } 43 for (int i = 1; i <= n; i++) { 44 cin >> a[i]; 45 int x = fin(i), y = fin(a[i]); 46 if (rankv[x] < rankv[y]) { 47 fa[x] = y; 48 } 49 else { 50 fa[y] = x; 51 if (rankv[y] == rankv[x]) { 52 ++rankv[x]; 53 54 } 55 } 56 } 57 for (int i = 1; i <= n; i++) { 58 if (visited[fin(i)] == 0) { 59 visited[fin(i)] = 1; 60 dfs(fin(i)); 61 } 62 } 63 printf("%lld\n", ans); 64 return 0; 65 }