# import sys
# input = sys.stdin.buffer.readline
from collections import deque

class Graph(object):
	"""docstring for Graph"""
	def __init__(self,n,d): # Number of nodes and d is True if directed
		self.n = n
		self.graph = [[] for i in range(n)]
		self.parent = [-1 for i in range(n)]
		self.directed = d

	def addEdge(self,x,y):
		self.graph[x].append(y)
		if not self.directed:
			self.graph[y].append(x)

	def bfs(self, root): # NORMAL BFS
		self.parent = [-1 for i in range(self.n)]
		queue = [root]
		queue = deque(queue)
		vis = [0]*self.n
		while len(queue)!=0:
			element = queue.popleft()
			vis[element] = 1
			for i in self.graph[element]:
				if vis[i]==0:
					queue.append(i)
					self.parent[i] = element

	def dfs(self, root, ans): # Iterative DFS
		stack=[root]
		vis=[0]*self.n
		stack2=[]
		while len(stack)!=0: # INITIAL TRAVERSAL
			element = stack.pop()
			if vis[element]:
				continue
			vis[element] = 1
			stack2.append(element)
			for i in self.graph[element]:
				if vis[i]==0:
					self.parent[i] = element
					stack.append(i)

		while len(stack2)!=0: # BACKTRACING. Modify the loop according to the question
			element = stack2.pop()
			m = 0
			for i in self.graph[element]:
				if i!=self.parent[element]:
					m += ans[i]
			ans[element] = m
		return ans

	def shortestpath(self, source, dest): # Calculate Shortest Path between two nodes
		self.bfs(source)
		path = [dest]
		while self.parent[path[-1]]!=-1:
			path.append(parent[path[-1]])
		return path[::-1]

	def ifcycle(self, root, vis):
		self.bfs(root)
		queue = [root]
		queue = deque(queue)
		done = {root:1}
		prev = root
		while len(queue)!=0:
			element = queue.popleft()
			prev = element
			vis[element] = 1
			for i in self.graph[element]:
				if i in done:
					cycle = [element]
					while cycle[-1]!=i:
						cycle.append(self.parent[cycle[-1]])
					return (True,cycle)

				if vis[i]==1:
					return (False,-1)

				if vis[i]==0:
					done[i]=1
					queue.append(i)
					vis[i] = 1
		return (False,prev)

	def reroot(self, root, ans):
		stack = [root]
		vis = [0]*n
		while len(stack)!=0:
			e = stack[-1]
			if vis[e]:
				stack.pop()
				# Reverse_The_Change()
				continue
			vis[e] = 1
			for i in graph[e]:
				if not vis[e]:
					stack.append(i)
			if self.parent[e]==-1:
				continue
			# Change_The_Answers()

n = int(input())
g = Graph(n,True)
cost = list(map(int,raw_input().split()))
l = list(map(int,raw_input().split()))
vis = [0]*n
ans = 0
for i in range(n):
	if vis[i]==0:
		curr=i
		temp = cost[curr]
		flag = 0
		done = {curr:1}
		while True:
			if vis[curr]==1:
				if curr not in done:
					flag = 2
					break
				flag = 1
				break
			done[curr]=1
			vis[curr]=1
			if curr!=l[curr]-1:
				temp = cost[l[curr]-1]
			else:
				break
			curr = l[curr]-1
		if flag==2:
			continue
		if not flag:
			ans+=temp
		else:
			nxt = l[curr]-1
			temp = cost[nxt]
			while nxt!=curr:
				nxt = l[nxt]-1
				temp = min(cost[nxt],temp)
			ans+=temp
		# print (ans,temp,flag,i)

print (ans)


# import sys
# input = sys.stdin.buffer.readline
from collections import deque

class Graph(object):
	"""docstring for Graph"""
	def __init__(self,n,d): # Number of nodes and d is True if directed
		self.n = n
		self.graph = [[] for i in range(n)]
		self.parent = [-1 for i in range(n)]
		self.directed = d

	def addEdge(self,x,y):
		self.graph[x].append(y)
		if not self.directed:
			self.graph[y].append(x)

	def bfs(self, root): # NORMAL BFS
		self.parent = [-1 for i in range(self.n)]
		queue = [root]
		queue = deque(queue)
		vis = [0]*self.n
		while len(queue)!=0:
			element = queue.popleft()
			vis[element] = 1
			for i in self.graph[element]:
				if vis[i]==0:
					queue.append(i)
					self.parent[i] = element

	def dfs(self, root, ans): # Iterative DFS
		stack=[root]
		vis=[0]*self.n
		stack2=[]
		while len(stack)!=0: # INITIAL TRAVERSAL
			element = stack.pop()
			if vis[element]:
				continue
			vis[element] = 1
			stack2.append(element)
			for i in self.graph[element]:
				if vis[i]==0:
					self.parent[i] = element
					stack.append(i)

		while len(stack2)!=0: # BACKTRACING. Modify the loop according to the question
			element = stack2.pop()
			m = 0
			for i in self.graph[element]:
				if i!=self.parent[element]:
					m += ans[i]
			ans[element] = m
		return ans

	def shortestpath(self, source, dest): # Calculate Shortest Path between two nodes
		self.bfs(source)
		path = [dest]
		while self.parent[path[-1]]!=-1:
			path.append(parent[path[-1]])
		return path[::-1]

	def ifcycle(self, root, vis):
		self.bfs(root)
		queue = [root]
		queue = deque(queue)
		done = {root:1}
		prev = root
		while len(queue)!=0:
			element = queue.popleft()
			prev = element
			vis[element] = 1
			for i in self.graph[element]:
				if i in done:
					cycle = [element]
					while cycle[-1]!=i:
						cycle.append(self.parent[cycle[-1]])
					return (True,cycle)

				if vis[i]==1:
					return (False,-1)

				if vis[i]==0:
					done[i]=1
					queue.append(i)
					vis[i] = 1
		return (False,prev)

	def reroot(self, root, ans):
		stack = [root]
		vis = [0]*n
		while len(stack)!=0:
			e = stack[-1]
			if vis[e]:
				stack.pop()
				# Reverse_The_Change()
				continue
			vis[e] = 1
			for i in graph[e]:
				if not vis[e]:
					stack.append(i)
			if self.parent[e]==-1:
				continue
			# Change_The_Answers()

n = int(input())
g = Graph(n,True)
cost = list(map(int,raw_input().split()))
l = list(map(int,raw_input().split()))
vis = [0]*n
for i in range(n):
	if vis[i]==0:
		curr=i
		while True:
			if vis[curr]==1:
				break
			vis[curr]=1
			if curr!=l[curr]-1:
				g.addEdge(curr,l[curr]-1)
			# print (curr,l[curr],g.graph)
			curr = l[curr]-1
# print (g.graph)
if n==200000:
	print (1/0)
vis = [0]*n
ans = 0
for i in range(n):
	if vis[i]==0:
		temp = g.ifcycle(i, vis)
		if not temp[0]:
			if temp[1]!=-1:
				ans+=cost[temp[1]]
		else:
			m=10**18
			for c in temp[1]:
				m=min(m,cost[c])
			ans+=m
		# print (ans,temp,i)
print (ans)


#include <stdio.h>
#include <string.h>

#define N	200000
#define C	10000

int main() {
	static int cc[N], aa[N], ii[N];
	int n, i, j, j_, ans, min;

	scanf("%d", &n);
	for (i = 0; i < n; i++)
		scanf("%d", &cc[i]);
	for (i = 0; i < n; i++) {
		scanf("%d", &aa[i]);
		aa[i]--;
	}
	memset(ii, -1, sizeof ii);
	ans = 0;
	for (i = 0; i < n; i++)
		if (ii[i] == -1) {
			j = i;
			while (ii[j] == -1) {
				ii[j] = i;
				j = aa[j];
			}
			if (ii[j] == i) {
				j_ = j;
				min = C + 1;
				do {
					if (min > cc[j_])
						min = cc[j_];
					j_ = aa[j_];
				} while (j_ != j);
				ans += min;
			}
		}
	printf("%d\n", ans);
	return 0;
}


#include<stdio.h>
#include<string.h>

int acc[200001] = {};
int cost[200001] = {};
int next[200001] = {};

int min(int a, int b){
	return a < b ? a : b;
}

int cycle(int idx, int sen, int path[]){
	int min = cost[idx];
	path[idx] = 0;
	idx = next[idx];
	while(idx != sen){
		if(cost[idx] < min){
			min = cost[idx];
		}
		path[idx] = 0;
		idx = next[idx];
	}
	return min;
}

int dfs(int idx, int path[]){
	if(acc[idx]) return 0;
	path[idx] = 1;
	acc[idx] = 1;
	int ne = next[idx];
	if(path[ne]){
		int sen = ne;
		int ret = cycle(ne, sen, path);
		return ret;
	}
	int ret = dfs(ne, path);
	path[idx] = 0;
	return ret;
}

int main(){
	int n;
	scanf("%d", &n);

	for(int i = 1 ; i <= n ; i++) scanf("%d", &cost[i]);
	for(int i = 1 ; i <= n ; i++) scanf("%d", &next[i]);

	int ans = 0;
	int path[200001] = {};
	for(int i = 1 ; i <= n ; i++){
		if(acc[i]) continue;
		ans += dfs(i, path);
	}

	printf("%d\n", ans);
}


#include<stdio.h>
#include<string.h>

int acc[200001] = {};
int cost[200001] = {};
int next[200001] = {};

int min(int a, int b){
	return a < b ? a : b;
}

int cycle(int idx, int sen){
	int min = cost[idx];
	idx = next[idx];
	while(idx != sen){
		if(cost[idx] < min){
			min = cost[idx];
		}
		idx = next[idx];
	}
	return min;
}

int dfs(int idx, int path[]){
	printf("idx: %d\n", idx);
	if(acc[idx]) return 0;
	path[idx] = 1;
	acc[idx] = 1;
	int ne = next[idx];
	if(path[ne]){
		int sen = ne;
		int ret = cycle(ne, sen);
		return ret;
	}
	return dfs(ne, path);
}

int main(){
	int n;
	scanf("%d", &n);

	for(int i = 1 ; i <= n ; i++) scanf("%d", &cost[i]);
	for(int i = 1 ; i <= n ; i++) scanf("%d", &next[i]);

	int ans = 0;
	int path[200001] = {};
	for(int i = 1 ; i <= n ; i++){
		if(acc[i]) continue;
		ans += dfs(i, path);
	}

	printf("%d\n", ans);
}


#include<stdio.h>
#include<string.h>

int acc[200001] = {};
int cost[200001] = {};
int next[200001] = {};

int min(int a, int b){
	return a < b ? a : b;
}

int cycle(int idx, int sen){
	int min = cost[idx];
	idx = next[idx];
	while(idx != sen){
		if(cost[idx] < min){
			min = cost[idx];
		}
		idx = next[idx];
	}
	return min;
}

int dfs(int idx, int path[]){
	if(acc[idx]) return 0;
	path[idx] = 1;
	acc[idx] = 1;
	int ne = next[idx];
	if(path[ne]){
		int sen = ne;
		int ret = cycle(ne, sen);
		path[ne] = 0;
		return ret;
	}
	int ret = dfs(ne, path);
	path[idx] = 0;
	return ret;
}

int main(){
	int n;
	scanf("%d", &n);

	for(int i = 1 ; i <= n ; i++) scanf("%d", &cost[i]);
	for(int i = 1 ; i <= n ; i++) scanf("%d", &next[i]);

	int ans = 0;
	int path[200001] = {};
	for(int i = 1 ; i <= n ; i++){
		if(acc[i]) continue;
		ans += dfs(i, path);
	}

	printf("%d\n", ans);
}


#include<stdio.h>
#include<string.h>

int cost[200001] = {};
int next[200001] = {};
int acc[200001] = {};
int cnt[200001] = {};
int critical[200001] = {};

int min(int a, int b){
	return a < b ? a : b;
}

void clear(int idx){
	int ne = next[idx];
	if(acc[ne] == 1){
		next[idx] = -1;
		return;
	}

	cnt[ne]++;

	if(acc[ne] == 2){
		acc[idx] = 2;
		return;
	}

	acc[idx] = 1;
	clear(ne);
	acc[idx] = 2;
}

int dfs(int idx){

	if(acc[idx]) return 0;

	int ne = next[idx];
	acc[idx] = 1;

	if(ne == -1) {
		critical[idx] = 1;
		return cost[idx];
	}

	int ret = dfs(ne);
	if(critical[ne]){
		critical[idx] = 1;
		if(cnt[idx] > 1){
			critical[idx] = 0;
		}
		return min(cost[idx], ret);
	}

	return ret;
}

int main(){
	int n;
	scanf("%d", &n);

	for(int i = 1 ; i <= n ; i ++){
		scanf("%d", &cost[i]);
	}

	for(int i = 1 ; i <= n ; i ++){
		scanf("%d", &next[i]);
	}

	for(int i = 1 ; i <= n ; i++){
		if(acc[i]) continue;
		clear(i);
	}

	memset(acc, 0 , sizeof(int) * (n+1));

	int ans = 0;
	for(int i = 1 ; i <= n ; i++){
		if(acc[i]) continue;
		memset(critical, 0, sizeof(int) * (n+1));
		ans += dfs(i);
	}

	printf("%d\n", ans);

}


#include<stdio.h>
#include<string.h>

int acc[200001] = {};
int cost[200001] = {};
int next[200001] = {};

int min(int a, int b){
	return a < b ? a : b;
}

int cycle(int idx, int sen){
	int min = cost[idx];
	idx = next[idx];
	while(idx != sen){
		if(cost[idx] < min){
			min = cost[idx];
		}
		idx = next[idx];
	}
	return min;
}

int dfs(int idx, int path[]){
	printf("idx: %d\n", idx);
	if(acc[idx]) return 0;
	path[idx] = 1;
	acc[idx] = 1;
	int ne = next[idx];
	if(path[ne]){
		int sen = ne;
		int ret = cycle(ne, sen);
		return ret;
	}
	return dfs(ne, path);
}

int main(){
	int n;
	scanf("%d", &n);

	for(int i = 1 ; i <= n ; i++) scanf("%d", &cost[i]);
	for(int i = 1 ; i <= n ; i++) scanf("%d", &next[i]);

	int ans = 0;
	int path[200001];
	for(int i = 1 ; i <= n ; i++){
		if(acc[i]) continue;
		ans += dfs(i, path);
	}

	printf("%d\n", ans);
}


#include<stdio.h>
#include<string.h>

int acc[200001] = {};
int cost[200001] = {};
int next[200001] = {};

int min(int a, int b){
	return a < b ? a : b;
}

int cycle(int idx, int sen){
	if(idx == sen) return cost[idx];
	return min(cost[idx], cycle(next[idx], sen));
}

int dfs(int idx, int path[]){
	if(acc[idx]) return 0;
	path[idx] = 1;
	acc[idx] = 1;
	int ne = next[idx];
	if(path[ne]){
		int sen = ne;
		int ret = cycle(next[ne], sen);
		return ret;
	}
	return dfs(ne, path);
}

int main(){
	int n;
	scanf("%d", &n);

	for(int i = 1 ; i <= n ; i++) scanf("%d", &cost[i]);
	for(int i = 1 ; i <= n ; i++) scanf("%d", &next[i]);

	int ans = 0;
	int path[200001];
	for(int i = 1 ; i <= n ; i++){
		if(acc[i]) continue;
		memset(path, 0, sizeof(int) * (n+1));
		ans += dfs(i, path);
	}

	printf("%d\n", ans);
}


#include<stdio.h>
#include<string.h>

int cost[200001] = {};
int next[200001] = {};
int acc[200001] = {};
int cnt[200001] = {};
int critical[200001] = {};

int min(int a, int b){
	return a < b ? a : b;
}

void clear(int idx){
	int ne = next[idx];
	if(acc[ne] == 1){
		next[idx] = -1;
		return;
	}

	cnt[ne]++;

	if(acc[ne] == 2){
		acc[idx] = 2;
		return;
	}

	acc[idx] = 1;
	clear(ne);
	acc[idx] = 2;
}

int dfs(int idx){
	if(acc[idx]) return 0;

	int ne = next[idx];
	acc[idx] = 1;

	if(ne == -1) {
		critical[idx] = 1;
		return cost[idx];
	}

	if(cnt[idx] > 1){
		critical[idx] = 0;
	}

	int ret = dfs(ne);
	if(critical[ne]){
		return min(cost[idx], ret);
	}

	return ret;
}

int main(){
	int n;
	scanf("%d", &n);

	for(int i = 1 ; i <= n ; i ++){
		scanf("%d", &cost[i]);
	}

	for(int i = 1 ; i <= n ; i ++){
		scanf("%d", &next[i]);
	}

	for(int i = 1 ; i <= n ; i++){
		if(acc[i]) continue;
		clear(i);
	}

	memset(acc, 0 , sizeof(int) * (n+1));

	int ans = 0;
	for(int i = 1 ; i <= n ; i++){
		if(acc[i]) continue;
		memset(critical, 0, sizeof(int) * (n+1));
		ans += dfs(i);
	}

	printf("%d\n", ans);

}


#include<stdio.h>
#include<string.h>

int acc[200001] = {};
int cost[200001] = {};
int next[200001] = {};

int min(int a, int b){
	return a < b ? a : b;
}

int cycle(int idx, int sen){
	int min = cost[idx];
	idx = next[idx];
	while(idx != sen){
		if(cost[idx] < min){
			min = cost[idx];
		}
		idx = next[idx];
	}
	return min;
}

int dfs(int idx, int path[]){
	if(acc[idx]) return 0;
	path[idx] = 1;
	acc[idx] = 1;
	int ne = next[idx];
	if(path[ne]){
		int sen = ne;
		int ret = cycle(ne, sen);
		return ret;
	}
	return dfs(ne, path);
}

int main(){
	int n;
	scanf("%d", &n);

	for(int i = 1 ; i <= n ; i++) scanf("%d", &cost[i]);
	for(int i = 1 ; i <= n ; i++) scanf("%d", &next[i]);

	int ans = 0;
	int path[200001] = {};
	for(int i = 1 ; i <= n ; i++){
		if(acc[i]) continue;
		ans += dfs(i, path);
	}

	printf("%d\n", ans);
}


#include<stdio.h>
#include<string.h>

int acc[200001] = {};
int cost[200001] = {};
int next[200001] = {};

int min(int a, int b){
	return a < b ? a : b;
}

int cycle(int idx, int sen){
	int min = cost[idx];
	idx = next[idx];
	while(idx != sen){
		if(cost[idx] < min){
			min = cost[idx];
		}
		idx = next[idx];
	}
	return min;
}

int dfs(int idx, int path[]){
	if(acc[idx]) return 0;
	path[idx] = 1;
	acc[idx] = 1;
	int ne = next[idx];
	if(path[ne]){
		int sen = ne;
		int ret = cycle(ne, sen);
		return ret;
	}
	return dfs(ne, path);
}

int main(){
	int n;
	scanf("%d", &n);

	for(int i = 1 ; i <= n ; i++) scanf("%d", &cost[i]);
	for(int i = 1 ; i <= n ; i++) scanf("%d", &next[i]);

	int ans = 0;
	int path[200001];
	for(int i = 1 ; i <= n ; i++){
		if(acc[i]) continue;
		memset(path, 0, sizeof(int) * (n+1));
		ans += dfs(i, path);
	}

	printf("%d\n", ans);
}


#include<stdio.h>
#include<stdlib.h>
#include<math.h>

typedef long long int int64;

#define MAX(a,b) ((a)>(b)?(a):(b))
#define MIN(a,b) ((a)<(b)?(a):(b))
#define ABS(a) ((a)>(0)?(a):-(a))

void run(void){
  int n;
  scanf("%d",&n);
  int *c=(int *)malloc(sizeof(int)*(n+1));
  int i;
  for(i=1;i<=n;i++) scanf("%d",c+i);
  int *a=(int *)malloc(sizeof(int)*(n+1));
  for(i=1;i<=n;i++) scanf("%d",a+i);
  int sum=0;
  int *dp=(int *)calloc(n+1,sizeof(int));
  for(i=1;i<=n;i++){
    if(dp[i]!=0) continue;
    int x=i;
    while(dp[x]==0){
      dp[x]=i;
      x=a[x];
    }
    if(dp[x]!=i) continue;
    int min=10001;
    while(dp[x]==i){
      min=MIN(min,c[x]);
      dp[x]=-i;
      x=a[x];
    }
    sum+=min;
  }
  printf("%d\n",sum);
}

int main(void){
  run();
  return 0;
}


using System;
using System.Linq;
using CompLib.Util;

public class Program
{
    int N;
    int[] C, A;
    public void Solve()
    {
        var sc = new Scanner();
        N = sc.NextInt();
        C = sc.IntArray();
        A = sc.IntArray();
        for (int i = 0; i < N; i++)
        {
            A[i]--;
        }
        /*
         * 部屋iにトラップ置く
         * コストC_i
         *
         * ネズミ
         * iにいる時、A_iに移動
         *
         * どこにネズミいても捕まえられるようにトラップ置く
         *
         * コスト最小
         */

        /*
         * ネズミの挙動
         * ループまで移動 -a -> ループ -b
         *
         * b最小に置く
         *
         */
        long ans = 0;
        int[] f = new int[N];
        int t = 1;
        for (int i = 0; i < N; i++)
        {
            if (f[i] != 0) continue;
            int cur = i;
            while (f[cur] == 0)
            {
                f[cur] = t;
                cur = A[cur];
            }
            if (f[cur] == t)
            {
                int min = C[cur];
                int cur2 = A[cur];
                while (cur2 != cur)
                {
                    min = Math.Min(min, C[cur2]);
                    cur2 = A[cur2];
                }

                ans += min;
            }
            t++;
        }

        Console.WriteLine(ans);
    }

    public static void Main(string[] args) => new Program().Solve();
}

namespace CompLib.Util
{
    using System;
    using System.Linq;

    class Scanner
    {
        private string[] _line;
        private int _index;
        private const char Separator = ' ';

        public Scanner()
        {
            _line = new string[0];
            _index = 0;
        }

        public string Next()
        {
            if (_index >= _line.Length)
            {
                string s;
                do
                {
                    s = Console.ReadLine();
                } while (s.Length == 0);

                _line = s.Split(Separator);
                _index = 0;
            }

            return _line[_index++];
        }

        public string ReadLine()
        {
            _index = _line.Length;
            return Console.ReadLine();
        }

        public int NextInt() => int.Parse(Next());
        public long NextLong() => long.Parse(Next());
        public double NextDouble() => double.Parse(Next());
        public decimal NextDecimal() => decimal.Parse(Next());
        public char NextChar() => Next()[0];
        public char[] NextCharArray() => Next().ToCharArray();

        public string[] Array()
        {
            string s = Console.ReadLine();
            _line = s.Length == 0 ? new string[0] : s.Split(Separator);
            _index = _line.Length;
            return _line;
        }

        public int[] IntArray() => Array().Select(int.Parse).ToArray();
        public long[] LongArray() => Array().Select(long.Parse).ToArray();
        public double[] DoubleArray() => Array().Select(double.Parse).ToArray();
        public decimal[] DecimalArray() => Array().Select(decimal.Parse).ToArray();
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading;
using System.Runtime.CompilerServices;
using System.Text;
using System.Diagnostics;
using System.Numerics;
using static System.Console;
using static System.Convert;
using static System.Math;
using static Template;

class Solver
{
    public Scanner sc;
    public void Solve()
    {
        var N = sc.Int;
        var C = sc.ArrInt;
        var A = sc.ArrInt;
        for (int i = 0; i < N; i++)
        {
            A[i]--;
        }
        var use = new bool[N];
        var res = 0;
        for (int i = 0; i < N; i++)
        {
            if (use[i]) continue;
            var now = i;
            var st = new Stack<int>();
            while (!use[now])
            {
                use[now] = true;st.Push(now);
                now = A[now];
            }
            var f = now;
            var min = C[now];
            while (st.Any()&&st.Peek() != f)
            {
                now = st.Pop();
                chmin(ref min, C[now]);
            }
            if (st.Any()&&st.Peek()==f) res += min;
        }
        Console.WriteLine(res);
    }
}

#region Template
public static class Template
{
    static void Main(string[] args)
    {
        Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false });
        var sol = new Solver() { sc = new Scanner() };
        //var th = new Thread(sol.Solve, 1 << 26);th.Start();th.Join();
        sol.Solve();
        Console.Out.Flush();
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool chmin<T>(ref T a, T b) where T : IComparable<T> { if (a.CompareTo(b) > 0) { a = b; return true; } return false; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool chmax<T>(ref T a, T b) where T : IComparable<T> { if (a.CompareTo(b) < 0) { a = b; return true; } return false; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static void swap<T>(ref T a, ref T b) { var t = b; b = a; a = t; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static void swap<T>(this IList<T> A, int i, int j) { var t = A[i]; A[i] = A[j]; A[j] = t; }
    public static T[] Create<T>(int n, Func<T> f) { var rt = new T[n]; for (var i = 0; i < rt.Length; ++i) rt[i] = f(); return rt; }
    public static T[] Create<T>(int n, Func<int, T> f) { var rt = new T[n]; for (var i = 0; i < rt.Length; ++i) rt[i] = f(i); return rt; }
    public static void Out<T>(this IList<T> A, out T a) => a = A[0];
    public static void Out<T>(this IList<T> A, out T a, out T b) { a = A[0]; b = A[1]; }
    public static void Out<T>(this IList<T> A, out T a, out T b, out T c) { A.Out(out a, out b); c = A[2]; }
    public static void Out<T>(this IList<T> A, out T a, out T b, out T c, out T d) { A.Out(out a, out b, out c); d = A[3]; }
    public static string Concat<T>(this IEnumerable<T> A, string sp) => string.Join(sp, A);
    public static char ToChar(this int s, char begin = '0') => (char)(s + begin);
    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> A) => A.OrderBy(v => Guid.NewGuid());
    public static int CompareTo<T>(this T[] A, T[] B, Comparison<T> cmp = null) { cmp = cmp ?? Comparer<T>.Default.Compare; for (var i = 0; i < Min(A.Length, B.Length); i++) { int c = cmp(A[i], B[i]); if (c > 0) return 1; else if (c < 0) return -1; } if (A.Length == B.Length) return 0; if (A.Length > B.Length) return 1; else return -1; }
    public static int ArgMax<T>(this IList<T> A, Comparison<T> cmp = null) { cmp = cmp ?? Comparer<T>.Default.Compare; T max = A[0]; int rt = 0; for (int i = 1; i < A.Count; i++) if (cmp(max, A[i]) < 0) { max = A[i]; rt = i; } return rt; }
    public static T PopBack<T>(this List<T> A) { var v = A[A.Count - 1]; A.RemoveAt(A.Count - 1); return v; }
    public static void Fail<T>(T s) { Console.WriteLine(s); Console.Out.Close(); Environment.Exit(0); }
}
public class Scanner
{
    public string Str => Console.ReadLine().Trim();
    public int Int => int.Parse(Str);
    public long Long => long.Parse(Str);
    public double Double => double.Parse(Str);
    public int[] ArrInt => Str.Split(' ').Select(int.Parse).ToArray();
    public long[] ArrLong => Str.Split(' ').Select(long.Parse).ToArray();
    public char[][] Grid(int n) => Create(n, () => Str.ToCharArray());
    public int[] ArrInt1D(int n) => Create(n, () => Int);
    public long[] ArrLong1D(int n) => Create(n, () => Long);
    public int[][] ArrInt2D(int n) => Create(n, () => ArrInt);
    public long[][] ArrLong2D(int n) => Create(n, () => ArrLong);
    private Queue<string> q = new Queue<string>();
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public T Next<T>() { if (q.Count == 0) foreach (var item in Str.Split(' ')) q.Enqueue(item); return (T)Convert.ChangeType(q.Dequeue(), typeof(T)); }
    public void Make<T1>(out T1 v1) => v1 = Next<T1>();
    public void Make<T1, T2>(out T1 v1, out T2 v2) { v1 = Next<T1>(); v2 = Next<T2>(); }
    public void Make<T1, T2, T3>(out T1 v1, out T2 v2, out T3 v3) { Make(out v1, out v2); v3 = Next<T3>(); }
    public void Make<T1, T2, T3, T4>(out T1 v1, out T2 v2, out T3 v3, out T4 v4) { Make(out v1, out v2, out v3); v4 = Next<T4>(); }
    public void Make<T1, T2, T3, T4, T5>(out T1 v1, out T2 v2, out T3 v3, out T4 v4, out T5 v5) { Make(out v1, out v2, out v3, out v4); v5 = Next<T5>(); }
    public void Make<T1, T2, T3, T4, T5, T6>(out T1 v1, out T2 v2, out T3 v3, out T4 v4, out T5 v5, out T6 v6) { Make(out v1, out v2, out v3, out v4, out v5); v6 = Next<T6>(); }
    public void Make<T1, T2, T3, T4, T5, T6, T7>(out T1 v1, out T2 v2, out T3 v3, out T4 v4, out T5 v5, out T6 v6, out T7 v7) { Make(out v1, out v2, out v3, out v4, out v5, out v6); v7 = Next<T7>(); }
    public (T1, T2) Make<T1, T2>() { Make(out T1 v1, out T2 v2); return (v1, v2); }
    public (T1, T2, T3) Make<T1, T2, T3>() { Make(out T1 v1, out T2 v2, out T3 v3); return (v1, v2, v3); }
    public (T1, T2, T3, T4) Make<T1, T2, T3, T4>() { Make(out T1 v1, out T2 v2, out T3 v3, out T4 v4); return (v1, v2, v3, v4); }
}

#endregion


using System;
using System.IO;
using System.Text;
using System.Threading;

namespace Mouse_Hunt
{
    internal class Program
    {
        private static readonly StreamReader reader = new StreamReader(Console.OpenStandardInput(1024*10), Encoding.ASCII, false, 1024*10);
        private static readonly StreamWriter writer = new StreamWriter(Console.OpenStandardOutput(1024*10), Encoding.ASCII, 1024*10);

        private static int[] c;
        private static int[] a;
        private static int[] p;

        private static void Main(string[] args)
        {
            Thread t = new Thread(()=> writer.WriteLine(Solve(args)), 32*1024*1024);
            t.Start();
            t.Join();
            writer.Flush();
        }

        private static int Solve(string[] args)
        {
            int n = Next();

            c = new int[n];
            p = new int[n];
            for (int i = 0; i < n; i++)
            {
                c[i] = Next();
            }
            a = new int[n];
            for (int i = 0; i < n; i++)
            {
                a[i] = Next() - 1;
            }
            int sum = 0;
            for (int i = 0; i < n; i++)
            {
                if (p[i] == 0)
                {
                    int cycle;
                    sum += Dfs(i, out cycle);
                }
            }

            return sum;
        }

        private static int Dfs(int i, out int cycle)
        {
            if (p[i] == 0)
            {
                p[i] = 1;
                int v = Dfs(a[i], out cycle);
                p[i] = 2;
                if (cycle < 0)
                    return v;
                if (cycle == i)
                {
                    cycle = -1;
                }
                return Math.Min(v, c[i]);
            }
            if (p[i] == 2)
            {
                cycle = -1;
                return 0;
            }
            cycle = i;
            return c[i];
        }

        private static int Next()
        {
            int c;
            int res = 0;
            do
            {
                c = reader.Read();
                if (c == -1)
                    return res;
            } while (c < '0' || c > '9');
            res = c - '0';
            while (true)
            {
                c = reader.Read();
                if (c < '0' || c > '9')
                    return res;
                res *= 10;
                res += c - '0';
            }
        }
    }
}


using System;
using System.IO;
using System.Text;
using System.Threading;

namespace Mouse_Hunt
{
    internal class Program
    {
        private static readonly StreamReader reader = new StreamReader(Console.OpenStandardInput(1024*10), Encoding.ASCII, false, 1024*10);
        private static readonly StreamWriter writer = new StreamWriter(Console.OpenStandardOutput(1024*10), Encoding.ASCII, 1024*10);

        private static int[] c;
        private static int[] a;
        private static int[] p;

        private static void Main(string[] args)
        {
            Thread t = new Thread(()=> writer.WriteLine(Solve(args)), 4*1024*1024);
            t.Start();
            t.Join();
            writer.Flush();
        }

        private static int Solve(string[] args)
        {
            int n = Next();

            c = new int[n];
            p = new int[n];
            for (int i = 0; i < n; i++)
            {
                c[i] = Next();
            }
            a = new int[n];
            for (int i = 0; i < n; i++)
            {
                a[i] = Next() - 1;
            }
            int sum = 0;
            for (int i = 0; i < n; i++)
            {
                if (p[i] == 0)
                {
                    int cycle;
                    sum += Dfs(i, out cycle);
                }
            }

            return sum;
        }

        private static int Dfs(int i, out int cycle)
        {
            if (p[i] == 0)
            {
                p[i] = 1;
                int v = Dfs(a[i], out cycle);
                p[i] = 2;
                if (cycle < 0)
                    return v;
                if (cycle == i)
                {
                    cycle = -1;
                }
                return Math.Min(v, c[i]);
            }
            if (p[i] == 2)
            {
                cycle = -1;
                return 0;
            }
            cycle = i;
            return c[i];
        }

        private static int Next()
        {
            int c;
            int res = 0;
            do
            {
                c = reader.Read();
                if (c == -1)
                    return res;
            } while (c < '0' || c > '9');
            res = c - '0';
            while (true)
            {
                c = reader.Read();
                if (c < '0' || c > '9')
                    return res;
                res *= 10;
                res += c - '0';
            }
        }
    }
}


using System;
using System.IO;
using System.Text;
using System.Threading;

namespace Mouse_Hunt
{
    internal class Program
    {
        private static readonly StreamReader reader = new StreamReader(Console.OpenStandardInput(1024*10), Encoding.ASCII, false, 1024*10);
        private static readonly StreamWriter writer = new StreamWriter(Console.OpenStandardOutput(1024*10), Encoding.ASCII, 1024*10);

        private static int[] c;
        private static int[] a;
        private static int[] p;

        private static void Main(string[] args)
        {
            Thread t = new Thread(()=> writer.WriteLine(Solve(args)), 64*1024*1024);
            t.Start();
            t.Join();
            writer.Flush();
        }

        private static int Solve(string[] args)
        {
            int n = Next();

            c = new int[n];
            p = new int[n];
            for (int i = 0; i < n; i++)
            {
                c[i] = Next();
            }
            a = new int[n];
            for (int i = 0; i < n; i++)
            {
                a[i] = Next() - 1;
            }
            int sum = 0;
            for (int i = 0; i < n; i++)
            {
                if (p[i] == 0)
                {
                    int cycle;
                    sum += Dfs(i, out cycle);
                }
            }

            return sum;
        }

        private static int Dfs(int i, out int cycle)
        {
            if (p[i] == 0)
            {
                p[i] = 1;
                int v = Dfs(a[i], out cycle);
                p[i] = 2;
                if (cycle < 0)
                    return v;
                if (cycle == i)
                {
                    cycle = -1;
                }
                return Math.Min(v, c[i]);
            }
            if (p[i] == 2)
            {
                cycle = -1;
                return 0;
            }
            cycle = i;
            return c[i];
        }

        private static int Next()
        {
            int c;
            int res = 0;
            do
            {
                c = reader.Read();
                if (c == -1)
                    return res;
            } while (c < '0' || c > '9');
            res = c - '0';
            while (true)
            {
                c = reader.Read();
                if (c < '0' || c > '9')
                    return res;
                res *= 10;
                res += c - '0';
            }
        }
    }
}


using System;
using System.IO;
using System.Text;

namespace Mouse_Hunt
{
    internal class Program
    {
        private static readonly StreamReader reader = new StreamReader(Console.OpenStandardInput(1024*10), Encoding.ASCII, false, 1024*10);
        private static readonly StreamWriter writer = new StreamWriter(Console.OpenStandardOutput(1024*10), Encoding.ASCII, 1024*10);

        private static int[] c;
        private static int[] a;
        private static int[] p;

        private static void Main(string[] args)
        {
            writer.WriteLine(Solve(args));
            writer.Flush();
        }

        private static int Solve(string[] args)
        {
            int n = Next();

            c = new int[n];
            p = new int[n];
            for (int i = 0; i < n; i++)
            {
                c[i] = Next();
            }
            a = new int[n];
            for (int i = 0; i < n; i++)
            {
                a[i] = Next() - 1;
            }
            int sum = 0;
            for (int i = 0; i < n; i++)
            {
                if (p[i] == 0)
                {
                    int cycle;
                    sum += Dfs(i, out cycle);
                }
            }

            return sum;
        }

        private static int Dfs(int i, out int cycle)
        {
            if (p[i] == 0)
            {
                p[i] = 1;
                int v = Dfs(a[i], out cycle);
                p[i] = 2;
                if (cycle < 0)
                    return v;
                if (cycle == i)
                {
                    cycle = -1;
                }
                return Math.Min(v, c[i]);
            }
            if (p[i] == 2)
            {
                cycle = -1;
                return 0;
            }
            cycle = i;
            return c[i];
        }

        private static int Next()
        {
            int c;
            int res = 0;
            do
            {
                c = reader.Read();
                if (c == -1)
                    return res;
            } while (c < '0' || c > '9');
            res = c - '0';
            while (true)
            {
                c = reader.Read();
                if (c < '0' || c > '9')
                    return res;
                res *= 10;
                res += c - '0';
            }
        }
    }
}


using System;
using System.Linq;

namespace cf_er49_d2_d
{
	class Program
	{
		public static void Main(string[] args)
		{
			var n = int.Parse(Console.ReadLine());
			var costs = Array.ConvertAll(Console.ReadLine().Split(' '), int.Parse);
			var rooms = Array.ConvertAll(Console.ReadLine().Split(' '), room => int.Parse(room) - 1);
			var fromRoom = Enumerable.Repeat(-1, n).ToArray();
			var sum = 0;

			for (int i = 0; i < n; i++)
			{
				if (fromRoom[i] != -1)
					continue;

				var startOfCycle = LaunchMouse(i, rooms, fromRoom);
				if (fromRoom[startOfCycle] == i)
				{
					sum += FindMinOnCyrcle(startOfCycle, rooms, costs);
				}
			}

			Console.WriteLine(sum);
		}

		private static int LaunchMouse(int number, int[] rooms, int[] fromRoom)
		{
			var i = number;

			do
			{
				fromRoom[i] = number;
				i = rooms[i];
			}
			while (fromRoom[i] == -1);

			return i;
		}

		private static int FindMinOnCyrcle(int startOfCycle, int[] rooms, int[] costs)
		{
			var i = startOfCycle;
			var min = costs[i];

			do
			{
				i = rooms[i];
				min = Math.Min(min, costs[i]);
			}
			while (i != startOfCycle);

			return min;
		}
	}
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.IO;
using System.Collections;
using System.Globalization;

// binary search --> use inclusive bounds and condition <=
//Array.Reverse do not work in mono!
namespace CodePractice
{

    public class Test
    {
        public static void Main()
        {
            ConsoleReader r = new ConsoleReader();
            TextWriter w = new StreamWriter(new BufferedStream(Console.OpenStandardOutput()));
            Solve(r, w);
            w.Close();
            //Console.ReadKey();
        }

        public static void Solve(ConsoleReader reader, TextWriter writer)
        {
            D(reader, writer);
        }

        public static void E(ConsoleReader reader, TextWriter writer)
        {
        }

        public static void D(ConsoleReader reader, TextWriter writer)
        {
            int n = reader.NextInt();
            int[] cost = reader.NextIntArray(n), graph = new int[n], inDeg = new int[n];
            int[] component = new int[n];

            for (int i = 0; i < n; i++)
            {
                graph[i] = reader.NextInt() - 1;
                inDeg[graph[i]]++;
            }

            int minCost = 0;
            int componentId = 1;
            for (int i = 0; i < n; i++)
            {
                if (inDeg[i] > 0 && component[i] == 0)
                {
                    int x = DfsMinCost(graph, component, cost, i, componentId++);
                    minCost += x;
                }
            }
            writer.WriteLine(minCost);
        }

        public static int DfsMinCost(int[] graph, int[] component, int[] cost, int node, int cid)
        {
            component[node] = cid;
            int min = cost[node];

            if (component[graph[node]] == 0)
            {
                min = Math.Min(min, DfsMinCost(graph, component, cost, graph[node], cid));
            }
            else if (component[graph[node]] != cid)
            {
                //already visited but different component
                return 0;
            }
            return min;
        }

        public static void C(ConsoleReader reader, TextWriter writer)
        {
        }

        public static void B(ConsoleReader reader, TextWriter writer)
        {

        }

        public static void A(ConsoleReader reader, TextWriter writer)
        {
            //
        }
    }

    public class ConsoleReader
    {
        private String[] data;
        private int wordIndex = 0;

        private void ReadLineIfNeeded()
        {
            while (data == null || wordIndex >= data.Length)
            {
                wordIndex = 0;
                data = Console.ReadLine().Trim().Split();
            }
        }

        public long NextLong()
        {
            ReadLineIfNeeded();
            return long.Parse(data[wordIndex++]);
        }

        public int NextInt()
        {
            ReadLineIfNeeded();
            return int.Parse(data[wordIndex++]);
        }

        public long[] NextLongArray(int n)
        {
            long[] a = new long[n];
            for (int i = 0; i < n; i++)
            {
                a[i] = NextLong();
            }
            return a;
        }

        public int[] NextIntArray(int n)
        {
            int[] a = new int[n];
            for (int i = 0; i < n; i++)
            {
                a[i] = NextInt();
            }
            return a;
        }

        public string NextString()
        {
            ReadLineIfNeeded();
            return data[wordIndex++];
        }

        //ReadLine()

    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.IO;
using System.Collections;
using System.Globalization;

// binary search --> use inclusive bounds and condition <=
//Array.Reverse do not work in mono!
namespace CodePractice
{

    public class Test
    {
        public static void Main()
        {
            ConsoleReader r = new ConsoleReader();
            TextWriter w = new StreamWriter(new BufferedStream(Console.OpenStandardOutput()));
            Solve(r, w);
            w.Close();
            //Console.ReadKey();
        }

        public static void Solve(ConsoleReader reader, TextWriter writer)
        {
            D(reader, writer);
        }

        public static void E(ConsoleReader reader, TextWriter writer)
        {
        }

        public static void D(ConsoleReader reader, TextWriter writer)
        {
            int n = reader.NextInt();
            int[] cost = reader.NextIntArray(n), graph = new int[n], inDeg = new int[n];
            int[] component = new int[n];

            for (int i = 0; i < n; i++)
            {
                graph[i] = reader.NextInt() - 1;
                inDeg[graph[i]]++;
            }

            int minCost = 0;
            int componentId = 1;
            for (int i = 0; i < n; i++)
            {
                if (inDeg[i] > 0 && component[i] == 0)
                {
                    int x = DfsMinCost(graph, component, cost, i, componentId++);
                    minCost += x;
                }
            }
            writer.WriteLine(minCost);
        }

        public static int DfsMinCost(int[] graph, int[] component, int[] cost, int node, int cid)
        {
            component[node] = cid;
            while(component[graph[node]] == 0)
            {
                component[graph[node]] = cid;
                node = graph[node];
            }

            if (component[graph[node]] != cid)
            {
                //already visited but different component
                return 0;
            }
            else
            {
                int min = cost[node];
                int start = node;
                //traverse cycle and get min
                while (graph[node] != start)
                {
                    min = Math.Min(min, cost[graph[node]]);
                    node = graph[node];
                }
                return min;
            }
        }

        public static void C(ConsoleReader reader, TextWriter writer)
        {
        }

        public static void B(ConsoleReader reader, TextWriter writer)
        {

        }

        public static void A(ConsoleReader reader, TextWriter writer)
        {
            //
        }
    }

    public class ConsoleReader
    {
        private String[] data;
        private int wordIndex = 0;

        private void ReadLineIfNeeded()
        {
            while (data == null || wordIndex >= data.Length)
            {
                wordIndex = 0;
                data = Console.ReadLine().Trim().Split();
            }
        }

        public long NextLong()
        {
            ReadLineIfNeeded();
            return long.Parse(data[wordIndex++]);
        }

        public int NextInt()
        {
            ReadLineIfNeeded();
            return int.Parse(data[wordIndex++]);
        }

        public long[] NextLongArray(int n)
        {
            long[] a = new long[n];
            for (int i = 0; i < n; i++)
            {
                a[i] = NextLong();
            }
            return a;
        }

        public int[] NextIntArray(int n)
        {
            int[] a = new int[n];
            for (int i = 0; i < n; i++)
            {
                a[i] = NextInt();
            }
            return a;
        }

        public string NextString()
        {
            ReadLineIfNeeded();
            return data[wordIndex++];
        }

        //ReadLine()

    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.IO;
using System.Collections;
using System.Globalization;

// binary search --> use inclusive bounds and condition <=
//Array.Reverse do not work in mono!
namespace CodePractice
{

    public class Test
    {
        public static void Main()
        {
            ConsoleReader r = new ConsoleReader();
            TextWriter w = new StreamWriter(new BufferedStream(Console.OpenStandardOutput()));
            Solve(r, w);
            w.Close();
            //Console.ReadKey();
        }

        public static void Solve(ConsoleReader reader, TextWriter writer)
        {
            D(reader, writer);
        }

        public static void E(ConsoleReader reader, TextWriter writer)
        {
        }

        public static void D(ConsoleReader reader, TextWriter writer)
        {
            int n = reader.NextInt();
            int[] cost = reader.NextIntArray(n), graph = new int[n], inDeg = new int[n];
            int[] component = new int[n];

            for (int i = 0; i < n; i++)
            {
                graph[i] = reader.NextInt() - 1;
                inDeg[graph[i]]++;
            }

            int minCost = 0;
            int componentId = 1;
            for (int i = 0; i < n; i++)
            {
                if (inDeg[i] > 0 && component[i] == 0)
                {
                    int x = DfsMinCost(graph, component, cost, i, componentId++);
                    minCost += x;
                }
            }
            writer.WriteLine(minCost);
        }

        public static int DfsMinCost(int[] graph, int[] component, int[] cost, int node, int cid)
        {
            component[node] = cid;
            int min = cost[node];

            while(component[graph[node]] == 0)
            {
                min = Math.Min(min, cost[graph[node]]);
                component[graph[node]] = cid;
                node = graph[node];
            }

            if (component[graph[node]] != cid)
            {
                //already visited but different component
                return 0;
            }
            return min;
        }

        public static void C(ConsoleReader reader, TextWriter writer)
        {
        }

        public static void B(ConsoleReader reader, TextWriter writer)
        {

        }

        public static void A(ConsoleReader reader, TextWriter writer)
        {
            //
        }
    }

    public class ConsoleReader
    {
        private String[] data;
        private int wordIndex = 0;

        private void ReadLineIfNeeded()
        {
            while (data == null || wordIndex >= data.Length)
            {
                wordIndex = 0;
                data = Console.ReadLine().Trim().Split();
            }
        }

        public long NextLong()
        {
            ReadLineIfNeeded();
            return long.Parse(data[wordIndex++]);
        }

        public int NextInt()
        {
            ReadLineIfNeeded();
            return int.Parse(data[wordIndex++]);
        }

        public long[] NextLongArray(int n)
        {
            long[] a = new long[n];
            for (int i = 0; i < n; i++)
            {
                a[i] = NextLong();
            }
            return a;
        }

        public int[] NextIntArray(int n)
        {
            int[] a = new int[n];
            for (int i = 0; i < n; i++)
            {
                a[i] = NextInt();
            }
            return a;
        }

        public string NextString()
        {
            ReadLineIfNeeded();
            return data[wordIndex++];
        }

        //ReadLine()

    }
}


#![allow(unused_imports)]
#![allow(non_snake_case)]

use std::cell::RefCell;
use std::cmp::{max, min, Ordering};
use std::collections::*;
use std::fmt::{Debug, Formatter, Write as FmtWrite};
use std::io::{stderr, stdin, BufRead, Write};
use std::mem::{replace, swap};
use std::ops::*;
use std::rc::Rc;

// -----------------------------------------------
// Framework <https://github.com/vain0x/procon>
// -----------------------------------------------

#[allow(unused_macros)]
macro_rules! read {
    ([$t:ty] ; $n:expr) =>
        ((0..$n).map(|_| read!([$t])).collect::<Vec<_>>());
    ($($t:ty),+ ; $n:expr) =>
        ((0..$n).map(|_| read!($($t),+)).collect::<Vec<_>>());
    ([$t:ty]) =>
        (rl().split_whitespace().map(|w| w.parse().unwrap()).collect::<Vec<$t>>());
    ($t:ty) =>
        (rl().parse::<$t>().unwrap());
    ($($t:ty),*) => {{
        let buf = rl();
        let mut w = buf.split_whitespace();
        ($(w.next().unwrap().parse::<$t>().unwrap()),*)
    }};
}

#[allow(unused_macros)]
macro_rules! debug {
    ($($arg:expr),*) => {
        #[cfg(debug_assertions)]
        $(writeln!(stderr(), "{} = {:?}", stringify!($arg), $arg).unwrap());*
    };
}

#[allow(dead_code)]
fn rl() -> String {
    let mut buf = String::new();
    stdin().read_line(&mut buf).unwrap();
    buf.trim_right().to_owned()
}

trait IteratorExt: Iterator + Sized {
    fn vec(self) -> Vec<Self::Item> {
        self.collect()
    }
}

impl<T: Iterator> IteratorExt for T {}

// -----------------------------------------------
// Solution
// -----------------------------------------------

#[derive(PartialEq, Eq, Clone, Copy, Debug)]
enum Color {
    White,
    Grey,
    Black,
}

#[derive(Debug)]
struct Solver {
    C: Vec<i64>,
    A: Vec<usize>,
    state: Vec<Color>,
    order: Vec<usize>,
    reent_order: usize,
    next_order: usize,
    mi: Option<i64>,
}

impl Solver {
    fn solve() {
        let N = read!(usize);
        let C = read![[i64]];
        let mut A = read![[usize]];
        for v in 0..N {
            A[v] -= 1;
        }
        // let N = 100000;
        // let C = vec![1; N];
        // let A = (0..N).map(|i| (i + 1) % N).vec();

        let mut it = Solver {
            C: C,
            A: A,
            state: vec![Color::White; N],
            order: vec![N; N],
            reent_order: 0,
            next_order: 0,
            mi: None,
        };

        let mut sum = 0_i64;
        for v in 0..N {
            it.mi = None;
            it.reent_order = N;

            if it.state[v] == Color::White {
                it.reent(v);
            }
            if let Some(mi) = it.mi {
                sum += mi;
            }

            // debug!(v, it);
        }
        println!("{}", sum)
    }

    fn reent(&mut self, v: usize) {
        self.state[v] = Color::Grey;
        self.order[v] = self.next_order;
        self.next_order += 1;

        let u = self.A[v];
        match self.state[u] {
            Color::White => {
                self.reent(u);
            }
            Color::Grey => {
                self.reent_order = self.order[u];
            }
            Color::Black => {}
        }

        if self.order[v] >= self.reent_order {
            let c = self.C[v];
            self.mi = Some(match self.mi {
                None => c,
                Some(mi) => min(mi, c),
            });
        }

        self.state[v] = Color::Black;
    }
}

fn main() {
    // Run on new thread with 64 MB stack
    // to avoid stack overflow.
    std::thread::Builder::new()
        .stack_size(64 * 1024 * 1024)
        .spawn(|| Solver::solve())
        .unwrap()
        .join()
        .unwrap()
}


#![allow(unused_imports)]
#![allow(non_snake_case)]

use std::cell::RefCell;
use std::cmp::{max, min, Ordering};
use std::collections::*;
use std::fmt::{Debug, Formatter, Write as FmtWrite};
use std::io::{stderr, stdin, BufRead, Write};
use std::mem::{replace, swap};
use std::ops::*;
use std::rc::Rc;

// -----------------------------------------------
// Framework <https://github.com/vain0x/procon>
// -----------------------------------------------

#[allow(unused_macros)]
macro_rules! read {
    ([$t:ty] ; $n:expr) =>
        ((0..$n).map(|_| read!([$t])).collect::<Vec<_>>());
    ($($t:ty),+ ; $n:expr) =>
        ((0..$n).map(|_| read!($($t),+)).collect::<Vec<_>>());
    ([$t:ty]) =>
        (rl().split_whitespace().map(|w| w.parse().unwrap()).collect::<Vec<$t>>());
    ($t:ty) =>
        (rl().parse::<$t>().unwrap());
    ($($t:ty),*) => {{
        let buf = rl();
        let mut w = buf.split_whitespace();
        ($(w.next().unwrap().parse::<$t>().unwrap()),*)
    }};
}

#[allow(unused_macros)]
macro_rules! debug {
    ($($arg:expr),*) => {
        #[cfg(debug_assertions)]
        $(writeln!(stderr(), "{} = {:?}", stringify!($arg), $arg).unwrap());*
    };
}

#[allow(dead_code)]
fn rl() -> String {
    let mut buf = String::new();
    stdin().read_line(&mut buf).unwrap();
    buf.trim_right().to_owned()
}

trait IteratorExt: Iterator + Sized {
    fn vec(self) -> Vec<Self::Item> {
        self.collect()
    }
}

impl<T: Iterator> IteratorExt for T {}

// -----------------------------------------------
// Solution
// -----------------------------------------------

fn main() {
    let N = read!(usize);
    let C = read![[i64]];
    let mut A = read![[usize]];

    let mut B = vec![vec![]; N];
    for v in 0..N {
        A[v] -= 1;
        B[A[v]].push(v);
    }

    let mut components = vec![];
    {
        let mut visited = vec![false; N];
        let mut stack = vec![];

        for u in 0..N {
            if visited[u] {
                continue;
            }

            let mut c = vec![];

            stack.push(u);
            while let Some(v) = stack.pop() {
                if visited[v] {
                    continue;
                }

                c.push(v);
                visited[v] = true;
                stack.push(A[v]);
                for b in &B[v] {
                    stack.push(*b);
                }
            }

            components.push(c);
        }
    }

    // debug!(components);

    let mut sum_cost = 0_i64;
    let mut order = vec![N; N];
    let mut next_order = 0;
    let mut stack = vec![];
    let mut path = vec![];

    for component in components {
        path.clear();
        stack.clear();
        stack.extend(component.iter().cloned());

        let mut mi_cost = std::i64::MAX;

        while let Some(v) = stack.pop() {
            if order[v] < N {
                while let Some(p) = path.pop() {
                    mi_cost = min(mi_cost, C[p]);
                    if p == v {
                        break;
                    }
                }
                break;
            }

            order[v] = next_order;
            next_order += 1;
            path.push(v);

            stack.push(A[v]);
        }

        // debug!(order, candidates);

        sum_cost += mi_cost;
    }

    println!("{}", sum_cost)
}


#![allow(unused_imports)]
#![allow(non_snake_case)]

use std::cell::RefCell;
use std::cmp::{max, min, Ordering};
use std::collections::*;
use std::fmt::{Debug, Formatter, Write as FmtWrite};
use std::io::{stderr, stdin, BufRead, Write};
use std::mem::{replace, swap};
use std::ops::*;
use std::rc::Rc;

// -----------------------------------------------
// Framework <https://github.com/vain0x/procon>
// -----------------------------------------------

#[allow(unused_macros)]
macro_rules! read {
    ([$t:ty] ; $n:expr) =>
        ((0..$n).map(|_| read!([$t])).collect::<Vec<_>>());
    ($($t:ty),+ ; $n:expr) =>
        ((0..$n).map(|_| read!($($t),+)).collect::<Vec<_>>());
    ([$t:ty]) =>
        (rl().split_whitespace().map(|w| w.parse().unwrap()).collect::<Vec<$t>>());
    ($t:ty) =>
        (rl().parse::<$t>().unwrap());
    ($($t:ty),*) => {{
        let buf = rl();
        let mut w = buf.split_whitespace();
        ($(w.next().unwrap().parse::<$t>().unwrap()),*)
    }};
}

#[allow(unused_macros)]
macro_rules! debug {
    ($($arg:expr),*) => {
        #[cfg(debug_assertions)]
        $(writeln!(stderr(), "{} = {:?}", stringify!($arg), $arg).unwrap());*
    };
}

#[allow(dead_code)]
fn rl() -> String {
    let mut buf = String::new();
    stdin().read_line(&mut buf).unwrap();
    buf.trim_right().to_owned()
}

trait IteratorExt: Iterator + Sized {
    fn vec(self) -> Vec<Self::Item> {
        self.collect()
    }
}

impl<T: Iterator> IteratorExt for T {}

// -----------------------------------------------
// Solution
// -----------------------------------------------

fn main() {
    let N = read!(usize);
    let C = read![[i64]];
    let mut A = read![[usize]];

    let mut B = vec![vec![]; N];
    for v in 0..N {
        A[v] -= 1;
        B[A[v]].push(v);
    }

    let mut components = vec![];
    {
        let mut visited = vec![false; N];
        let mut stack = vec![];

        for u in 0..N {
            if visited[u] {
                continue;
            }

            let mut c = vec![];

            stack.push(u);
            while let Some(v) = stack.pop() {
                if visited[v] {
                    continue;
                }

                c.push(v);
                visited[v] = true;
                stack.push(A[v]);
                for b in &B[v] {
                    stack.push(*b);
                }
            }

            components.push(c);
        }
    }

    // debug!(components);

    let mut sum_cost = 0_i64;

    for component in components {
        let mut order = vec![N; N];
        let mut next_order = 0;
        let mut stack = component.clone();
        let mut path = vec![];
        let mut candidates = vec![];

        while let Some(v) = stack.pop() {
            if order[v] < N {
                while let Some(p) = path.pop() {
                    candidates.push(p);
                    if p == v {
                        break;
                    }
                }
                break;
            }

            order[v] = next_order;
            next_order += 1;
            path.push(v);

            stack.push(A[v]);
        }

        // debug!(order, candidates);

        sum_cost += candidates.into_iter().map(|v| C[v]).min().unwrap();
    }

    println!("{}", sum_cost)
}


#![allow(unused_imports)]
#![allow(non_snake_case)]

use std::cell::RefCell;
use std::cmp::{max, min, Ordering};
use std::collections::*;
use std::fmt::{Debug, Formatter, Write as FmtWrite};
use std::io::{stderr, stdin, stdout, BufRead, Write};
use std::mem::{replace, swap};
use std::ops::*;
use std::rc::Rc;
// -----------------------------------------------
// Framework
// -----------------------------------------------

#[allow(unused_macros)]
macro_rules! read {
    ([$t:ty] ; $n:expr) =>
        ((0..$n).map(|_| read!([$t])).collect::<Vec<_>>());
    ($($t:ty),+ ; $n:expr) =>
        ((0..$n).map(|_| read!($($t),+)).collect::<Vec<_>>());
    ([$t:ty]) =>
        (rl().split_whitespace().map(|w| w.parse().unwrap()).collect::<Vec<$t>>());
    ($t:ty) =>
        (rl().parse::<$t>().unwrap());
    ($($t:ty),*) => {{
        let buf = rl();
        let mut w = buf.split_whitespace();
        ($(w.next().unwrap().parse::<$t>().unwrap()),*)
    }};
}
#[allow(dead_code)]
fn rl() -> String {
    let mut buf = String::new();
    stdin().read_line(&mut buf).unwrap();
    buf.trim_right().to_owned()
}

fn find_loop(start: u32, vis: &mut [u32], a: &[u32], c: &[u32]) -> u32 {
    if vis[start as usize] > 0 {
        return 0;
    }
    let mut _iter = start as usize;
    while vis[_iter] != start {
        if vis[_iter] > 0 {
            return 0;
        }
        vis[_iter] = start;
        _iter = a[_iter - 1] as usize;
    }
    let mut ret = 1e9 as u32;
    ret = min(ret, c[_iter - 1]);
    let loop_start = _iter;
    _iter = a[_iter - 1] as usize;
    while _iter != loop_start {
        ret = min(ret, c[_iter - 1]);
        _iter = a[_iter - 1] as usize;
    }
    println!("{}", ret);
    ret
}
fn main() {
    let n = read!(u32);
    let c = read!([u32]);
    let a = read!([u32]);
    let mut vis: Vec<u32> = vec![0; 200002 as usize];
    println!("{}", vis.len());
    let mut answer: u32 = 0;
    for start in 1..(n + 1) {
        answer += find_loop(start, &mut vis, &a, &c);
    }
    println!("{}", answer);
}
/*
5
1 2 3 2 10
1 3 4 3 3

 */


#![allow(unused_imports)]
#![allow(non_snake_case)]

use std::cell::RefCell;
use std::cmp::{max, min, Ordering};
use std::collections::*;
use std::fmt::{Debug, Formatter, Write as FmtWrite};
use std::io::{stderr, stdin, stdout, BufRead, Write};
use std::mem::{replace, swap};
use std::ops::*;
use std::rc::Rc;
// -----------------------------------------------
// Framework
// -----------------------------------------------

#[allow(unused_macros)]
macro_rules! read {
    ([$t:ty] ; $n:expr) =>
        ((0..$n).map(|_| read!([$t])).collect::<Vec<_>>());
    ($($t:ty),+ ; $n:expr) =>
        ((0..$n).map(|_| read!($($t),+)).collect::<Vec<_>>());
    ([$t:ty]) =>
        (rl().split_whitespace().map(|w| w.parse().unwrap()).collect::<Vec<$t>>());
    ($t:ty) =>
        (rl().parse::<$t>().unwrap());
    ($($t:ty),*) => {{
        let buf = rl();
        let mut w = buf.split_whitespace();
        ($(w.next().unwrap().parse::<$t>().unwrap()),*)
    }};
}
#[allow(dead_code)]
fn rl() -> String {
    let mut buf = String::new();
    stdin().read_line(&mut buf).unwrap();
    buf.trim_right().to_owned()
}

fn find_loop(start: u32, vis: &mut [u32], a: &[u32], c: &[u32]) -> u32 {
    if vis[start as usize] > 0 {
        return 0;
    }
    let mut _iter = start as usize;
    while vis[_iter] != start {
        if vis[_iter] > 0 {
            return 0;
        }
        vis[_iter] = start;
        _iter = a[_iter - 1] as usize;
    }
    let mut ret = 1e10 as u32;
    ret = min(ret, c[_iter - 1]);
    let loop_start = _iter;
    _iter = a[_iter - 1] as usize;
    while _iter != loop_start {
        ret = min(ret, c[_iter - 1]);
        _iter = a[_iter - 1] as usize;
    }
    println!("{}", ret);
    ret
}
fn main() {
    let n = read!(u32);
    let c = read!([u32]);
    let a = read!([u32]);
    let mut vis: Vec<u32> = vec![0; 200002 as usize];
    println!("{}", vis.len());
    let mut answer: u32 = 0;
    for start in 1..(n + 1) {
        answer += find_loop(start, &mut vis, &a, &c);
    }
    println!("{}", answer);
}
/*
5
1 2 3 2 10
1 3 4 3 3

 */


#![allow(unused_imports)]
#![allow(non_snake_case)]

use std::cell::RefCell;
use std::cmp::{max, min, Ordering};
use std::collections::*;
use std::fmt::{Debug, Formatter, Write as FmtWrite};
use std::io::{stderr, stdin, stdout, BufRead, Write};
use std::mem::{replace, swap};
use std::ops::*;
use std::rc::Rc;
// -----------------------------------------------
// Framework
// -----------------------------------------------

#[allow(unused_macros)]
macro_rules! read {
    ([$t:ty] ; $n:expr) =>
        ((0..$n).map(|_| read!([$t])).collect::<Vec<_>>());
    ($($t:ty),+ ; $n:expr) =>
        ((0..$n).map(|_| read!($($t),+)).collect::<Vec<_>>());
    ([$t:ty]) =>
        (rl().split_whitespace().map(|w| w.parse().unwrap()).collect::<Vec<$t>>());
    ($t:ty) =>
        (rl().parse::<$t>().unwrap());
    ($($t:ty),*) => {{
        let buf = rl();
        let mut w = buf.split_whitespace();
        ($(w.next().unwrap().parse::<$t>().unwrap()),*)
    }};
}
#[allow(dead_code)]
fn rl() -> String {
    let mut buf = String::new();
    stdin().read_line(&mut buf).unwrap();
    buf.trim_right().to_owned()
}

fn find_loop(start: usize, vis: &mut [usize], a: &[usize], c: &[usize]) -> usize {
    if vis[start] > 0 {
        return 0;
    }
    let mut _iter = start;
    while vis[_iter] != start {
        if vis[_iter] > 0 {
            return 0;
        }
        vis[_iter] = start;
        _iter = a[_iter - 1];
    }
    let mut ret: usize = 1e10 as usize;
    ret = min(ret, c[_iter - 1]);
    let loop_start = _iter;
    _iter = a[_iter - 1];
    while _iter != loop_start {
        ret = min(ret, c[_iter - 1]);
        _iter = a[_iter - 1];
    }
    ret
}
fn main() {
    let n = read!(usize);
    let c = read!([usize]);
    let a = read!([usize]);
    let mut vis: Vec<usize> = vec![0; 200002 as usize];
    let mut answer: usize = 0;
    for start in 1..(n + 1) {
        answer += find_loop(start, &mut vis, &a, &c);
        println!("{}", answer);
    }
    println!("{}", answer);
}


#![allow(unused_imports)]
#![allow(non_snake_case)]

use std::cell::RefCell;
use std::cmp::{max, min, Ordering};
use std::collections::*;
use std::fmt::{Debug, Formatter, Write as FmtWrite};
use std::io::{stderr, stdin, stdout, BufRead, Write};
use std::mem::{replace, swap};
use std::ops::*;
use std::rc::Rc;
// -----------------------------------------------
// Framework
// -----------------------------------------------

#[allow(unused_macros)]
macro_rules! read {
    ([$t:ty] ; $n:expr) =>
        ((0..$n).map(|_| read!([$t])).collect::<Vec<_>>());
    ($($t:ty),+ ; $n:expr) =>
        ((0..$n).map(|_| read!($($t),+)).collect::<Vec<_>>());
    ([$t:ty]) =>
        (rl().split_whitespace().map(|w| w.parse().unwrap()).collect::<Vec<$t>>());
    ($t:ty) =>
        (rl().parse::<$t>().unwrap());
    ($($t:ty),*) => {{
        let buf = rl();
        let mut w = buf.split_whitespace();
        ($(w.next().unwrap().parse::<$t>().unwrap()),*)
    }};
}
#[allow(dead_code)]
fn rl() -> String {
    let mut buf = String::new();
    stdin().read_line(&mut buf).unwrap();
    buf.trim_right().to_owned()
}

fn find_loop(start: usize, vis: &mut [usize], a: &[usize], c: &[usize]) -> u32 {
    if vis[start] > 0 {
        return 0;
    }
    let mut _iter = start;
    while vis[_iter] != start {
        if vis[_iter] > 0 {
            return 0;
        }
        vis[_iter] = start;
        _iter = a[_iter - 1];
    }
    let mut ret: u32 = 1e10 as u32;
    ret = min(ret, c[_iter - 1] as u32);
    let loop_start = _iter;
    _iter = a[_iter - 1];
    while _iter != loop_start {
        ret = min(ret, c[_iter - 1] as u32);
        _iter = a[_iter - 1];
    }
    println!("{}", ret);
    ret
}
fn main() {
    let n = read!(usize);
    let c = read!([usize]);
    let a = read!([usize]);
    let mut vis: Vec<usize> = vec![0; 200002 as usize];
    let mut answer: u32 = 0;
    for start in 1..(n + 1) {
        answer += find_loop(start, &mut vis, &a, &c);
    }
    println!("{}", answer);
}


#![allow(unused_imports)]
#![allow(non_snake_case)]

use std::cell::RefCell;
use std::cmp::{max, min, Ordering};
use std::collections::*;
use std::fmt::{Debug, Formatter, Write as FmtWrite};
use std::io::{stderr, stdin, stdout, BufRead, Write};
use std::mem::{replace, swap};
use std::ops::*;
use std::rc::Rc;
// -----------------------------------------------
// Framework
// -----------------------------------------------

#[allow(unused_macros)]
macro_rules! read {
    ([$t:ty] ; $n:expr) =>
        ((0..$n).map(|_| read!([$t])).collect::<Vec<_>>());
    ($($t:ty),+ ; $n:expr) =>
        ((0..$n).map(|_| read!($($t),+)).collect::<Vec<_>>());
    ([$t:ty]) =>
        (rl().split_whitespace().map(|w| w.parse().unwrap()).collect::<Vec<$t>>());
    ($t:ty) =>
        (rl().parse::<$t>().unwrap());
    ($($t:ty),*) => {{
        let buf = rl();
        let mut w = buf.split_whitespace();
        ($(w.next().unwrap().parse::<$t>().unwrap()),*)
    }};
}
#[allow(dead_code)]
fn rl() -> String {
    let mut buf = String::new();
    stdin().read_line(&mut buf).unwrap();
    buf.trim_right().to_owned()
}

fn find_loop(start: usize, vis: &mut [usize], a: &[usize], c: &[usize]) -> u32 {
    if vis[start] > 0 {
        return 0;
    }
    let mut _iter = start;
    while vis[_iter] != start {
        if vis[_iter] > 0 {
            return 0;
        }
        vis[_iter] = start;
        _iter = a[_iter - 1];
    }
    let mut ret: u32 = 1e10 as u32;
    ret = min(ret, c[_iter - 1] as u32);
    let loop_start = _iter;
    _iter = a[_iter - 1];
    while _iter != loop_start {
        ret = min(ret, c[_iter - 1] as u32);
        _iter = a[_iter - 1];
    }
    // println!("{}", ret);
    ret
}
fn main() {
    let n = read!(usize);
    let c = read!([usize]);
    let a = read!([usize]);
    let mut vis: Vec<usize> = vec![0; 200002 as usize];
    let mut answer: u32 = 0;
    for start in 1..(n + 1) {
        answer += find_loop(start, &mut vis, &a, &c);
    }
    println!("{}", answer);
}


#![allow(unused_imports)]
#![allow(non_snake_case)]

use std::cell::RefCell;
use std::cmp::{max, min, Ordering};
use std::collections::*;
use std::fmt::{Debug, Formatter, Write as FmtWrite};
use std::io::{stderr, stdin, stdout, BufRead, Write};
use std::mem::{replace, swap};
use std::ops::*;
use std::rc::Rc;
// -----------------------------------------------
// Framework
// -----------------------------------------------

#[allow(unused_macros)]
macro_rules! read {
    ([$t:ty] ; $n:expr) =>
        ((0..$n).map(|_| read!([$t])).collect::<Vec<_>>());
    ($($t:ty),+ ; $n:expr) =>
        ((0..$n).map(|_| read!($($t),+)).collect::<Vec<_>>());
    ([$t:ty]) =>
        (rl().split_whitespace().map(|w| w.parse().unwrap()).collect::<Vec<$t>>());
    ($t:ty) =>
        (rl().parse::<$t>().unwrap());
    ($($t:ty),*) => {{
        let buf = rl();
        let mut w = buf.split_whitespace();
        ($(w.next().unwrap().parse::<$t>().unwrap()),*)
    }};
}
#[allow(dead_code)]
fn rl() -> String {
    let mut buf = String::new();
    stdin().read_line(&mut buf).unwrap();
    buf.trim_right().to_owned()
}

fn find_loop(start: usize, vis: &mut [usize], a: &[usize], c: &[usize]) -> usize {
    if vis[start] > 0 {
        return 0;
    }
    let mut _iter = start;
    while vis[_iter] != start {
        if vis[_iter] > 0 {
            return 0;
        }
        vis[_iter] = start;
        _iter = a[_iter - 1];
    }
    let mut ret: usize = 1e10 as usize;
    ret = min(ret, c[_iter - 1]);
    let loop_start = _iter;
    _iter = a[_iter - 1];
    while _iter != loop_start {
        ret = min(ret, c[_iter - 1]);
        _iter = a[_iter - 1];
    }
    ret
}
fn main() {
    let n = read!(usize);
    let c = read!([usize]);
    let a = read!([usize]);
    let mut vis: Vec<usize> = vec![0; 200002 as usize];
    let mut answer: usize = 0;
    for start in 1..(n + 1) {
        answer += find_loop(start, &mut vis, &a, &c);
    }
    println!("{}", answer);
}


#![allow(unused_imports)]
#![allow(non_snake_case)]

use std::cell::RefCell;
use std::cmp::{max, min, Ordering};
use std::collections::*;
use std::fmt::{Debug, Formatter, Write as FmtWrite};
use std::io::{stderr, stdin, stdout, BufRead, Write};
use std::mem::{replace, swap};
use std::ops::*;
use std::rc::Rc;
// -----------------------------------------------
// Framework
// -----------------------------------------------

#[allow(unused_macros)]
macro_rules! read {
    ([$t:ty] ; $n:expr) =>
        ((0..$n).map(|_| read!([$t])).collect::<Vec<_>>());
    ($($t:ty),+ ; $n:expr) =>
        ((0..$n).map(|_| read!($($t),+)).collect::<Vec<_>>());
    ([$t:ty]) =>
        (rl().split_whitespace().map(|w| w.parse().unwrap()).collect::<Vec<$t>>());
    ($t:ty) =>
        (rl().parse::<$t>().unwrap());
    ($($t:ty),*) => {{
        let buf = rl();
        let mut w = buf.split_whitespace();
        ($(w.next().unwrap().parse::<$t>().unwrap()),*)
    }};
}
#[allow(dead_code)]
fn rl() -> String {
    let mut buf = String::new();
    stdin().read_line(&mut buf).unwrap();
    buf.trim_right().to_owned()
}

fn find_loop(start: usize, vis: &mut [usize], a: &[usize], c: &[usize]) -> usize {
    if vis[start] > 0 {
        return 0;
    }
    let mut _iter = start;
    while vis[_iter] != start {
        if vis[_iter] > 0 {
            return 0;
        }
        vis[_iter] = start;
        _iter = a[_iter - 1];
    }
    let mut ret: usize = 1e10 as usize;
    ret = min(ret, c[_iter - 1]);
    let loop_start = _iter;
    _iter = a[_iter - 1];
    while _iter != loop_start {
        ret = min(ret, c[_iter - 1]);
        _iter = a[_iter - 1];
    }
    println!("{}", ret);
    ret
}
fn main() {
    let n = read!(usize);
    let c = read!([usize]);
    let a = read!([usize]);
    let mut vis: Vec<usize> = vec![0; 200002 as usize];
    let mut answer: usize = 0;
    for start in 1..(n + 1) {
        answer += find_loop(start, &mut vis, &a, &c);
    }
    println!("{}", answer);
}


#![allow(unused_imports)]
#![allow(non_snake_case)]

use std::cell::RefCell;
use std::cmp::{max, min, Ordering};
use std::collections::*;
use std::fmt::{Debug, Formatter, Write as FmtWrite};
use std::io::{stderr, stdin, stdout, BufRead, Write};
use std::mem::{replace, swap};
use std::ops::*;
use std::rc::Rc;
// -----------------------------------------------
// Framework
// -----------------------------------------------

#[allow(unused_macros)]
macro_rules! read {
    ([$t:ty] ; $n:expr) =>
        ((0..$n).map(|_| read!([$t])).collect::<Vec<_>>());
    ($($t:ty),+ ; $n:expr) =>
        ((0..$n).map(|_| read!($($t),+)).collect::<Vec<_>>());
    ([$t:ty]) =>
        (rl().split_whitespace().map(|w| w.parse().unwrap()).collect::<Vec<$t>>());
    ($t:ty) =>
        (rl().parse::<$t>().unwrap());
    ($($t:ty),*) => {{
        let buf = rl();
        let mut w = buf.split_whitespace();
        ($(w.next().unwrap().parse::<$t>().unwrap()),*)
    }};
}
#[allow(dead_code)]
fn rl() -> String {
    let mut buf = String::new();
    stdin().read_line(&mut buf).unwrap();
    buf.trim_right().to_owned()
}

fn find_loop(start: u32, vis: &mut [u32], a: &[u32], c: &[u32]) -> u32 {
    if vis[start as usize] > 0 {
        return 0;
    }
    let mut _iter = start as usize;
    while vis[_iter] != start {
        if vis[_iter] > 0 {
            return 0;
        }
        vis[_iter] = start;
        _iter = a[_iter - 1] as usize;
    }
    let mut ret = 1e9 as u32;
    ret = min(ret, c[_iter - 1]);
    let loop_start = _iter;
    _iter = a[_iter - 1] as usize;
    while _iter != loop_start {
        ret = min(ret, c[_iter - 1]);
        _iter = a[_iter - 1] as usize;
    }
    // println!("{}", ret);
    ret
}
fn main() {
    let n = read!(u32);
    let c = read!([u32]);
    let a = read!([u32]);
    let mut vis: Vec<u32> = vec![0; 200002 as usize];
    // println!("{}", vis.len());
    let mut answer: u32 = 0;
    for start in 1..(n + 1) {
        answer += find_loop(start, &mut vis, &a, &c);
    }
    println!("{}", answer);
}
/*
5
1 2 3 2 10
1 3 4 3 3

 */


#![allow(unused_imports)]
#![allow(non_snake_case)]

use std::cell::RefCell;
use std::cmp::{max, min, Ordering};
use std::collections::*;
use std::fmt::{Debug, Formatter, Write as FmtWrite};
use std::io::{stderr, stdin, stdout, BufRead, Write};
use std::mem::{replace, swap};
use std::ops::*;
use std::rc::Rc;
// -----------------------------------------------
// Framework
// -----------------------------------------------

#[allow(unused_macros)]
macro_rules! read {
    ([$t:ty] ; $n:expr) =>
        ((0..$n).map(|_| read!([$t])).collect::<Vec<_>>());
    ($($t:ty),+ ; $n:expr) =>
        ((0..$n).map(|_| read!($($t),+)).collect::<Vec<_>>());
    ([$t:ty]) =>
        (rl().split_whitespace().map(|w| w.parse().unwrap()).collect::<Vec<$t>>());
    ($t:ty) =>
        (rl().parse::<$t>().unwrap());
    ($($t:ty),*) => {{
        let buf = rl();
        let mut w = buf.split_whitespace();
        ($(w.next().unwrap().parse::<$t>().unwrap()),*)
    }};
}

#[allow(unused_macros)]
macro_rules! debug {
    ($($arg:expr),*) => {
        #[cfg(debug_assertions)]
        $(writeln!(stderr(), "{} = {:?}", stringify!($arg), $arg).unwrap());*
    };
}

#[allow(dead_code)]
fn rl() -> String {
    let mut buf = String::new();
    stdin().read_line(&mut buf).unwrap();
    buf.trim_right().to_owned()
}

trait IteratorExt: Iterator + Sized {
    fn vec(self) -> Vec<Self::Item> {
        self.collect()
    }
}

impl<T: Iterator> IteratorExt for T {}

// -----------------------------------------------
// Solution
// -----------------------------------------------

fn find_loop(start: usize, vis: &mut[usize], a: &[usize], c: &[usize]) -> usize {
    if vis[start] > 0 {
        return 0;
    }
    let mut _iter  = start;
    while vis[_iter] != start {
        if vis[_iter] > 0 {
            return 0;
        }
        vis[_iter] = start;
        _iter = a[_iter - 1];
    }
    let mut ret: usize = 1e10 as usize;
    ret = min(ret, c[_iter - 1]);
    let loop_start = _iter;
    _iter = a[_iter - 1];
    while _iter != loop_start {
        ret = min(ret, c[_iter - 1]);
        _iter = a[_iter - 1];
    }
    ret
}
fn main() {
    let n = read!(usize);
    let c = read!([usize]);
    let a = read!([usize]);
    let mut vis: Vec<usize> = vec![0; 200002 as usize];
    let mut answer: usize = 0;
    for start in 1..n + 1 {
        answer += find_loop(start, &mut vis, &a, &c);
    }
    println!("{}", answer);
}


package main

import (
	"bufio"
	. "fmt"
	"io"
	"os"
)

// github.com/EndlessCheng/codeforces-go
func CF1027D(_r io.Reader, out io.Writer) {
	in := bufio.NewReader(_r)
	min := func(a, b int) int {
		if a < b {
			return a
		}
		return b
	}

	var n, s int
	Fscan(in, &n)
	c := make([]int, n)
	for i := range c {
		Fscan(in, &c[i])
	}
	g := make([]int, n)
	deg := make([]int, n)
	for i := range g {
		Fscan(in, &g[i])
		g[i]--
		deg[g[i]]++
	}

	vis := make([]bool, n)
	q := []int{}
	for i, d := range deg {
		if d == 0 {
			q = append(q, i)
		}
	}
	for len(q) > 0 {
		v := q[0]
		vis[v] = true
		q = q[1:]
		w := g[v]
		deg[w]--
		if deg[w] == 0 {
			q = append(q, w)
		}
	}

	var f func(int) int
	f = func(v int) int {
		vis[v] = true
		if vis[g[v]] {
			return c[v]
		}
		return min(f(g[v]), c[v])
	}
	for i, b := range vis {
		if !b {
			s += f(i)
		}
	}
	Fprint(out, s)
}

func main() { CF1027D(os.Stdin, os.Stdout) }


package main

import (
	"bufio"
	. "fmt"
	"io"
	"os"
)

// github.com/EndlessCheng/codeforces-go
func CF1027D(_r io.Reader, out io.Writer) {
	in := bufio.NewReader(_r)
	var n, s int
	Fscan(in, &n)
	c := make([]int, n)
	for i := range c {
		Fscan(in, &c[i])
	}
	g := make([]int, n)
	deg := make([]int, n)
	for i := range g {
		Fscan(in, &g[i])
		g[i]--
		deg[g[i]]++
	}

	vis := make([]bool, n)
	q := []int{}
	for i, d := range deg {
		if d == 0 {
			q = append(q, i)
		}
	}
	for len(q) > 0 {
		v := q[0]
		q = q[1:]
		vis[v] = true
		w := g[v]
		deg[w]--
		if deg[w] == 0 {
			q = append(q, w)
		}
	}

	for i, b := range vis {
		if !b {
			min := int(1e9)
			for v := i; !vis[v]; v = g[v] {
				vis[v] = true
				if c[v] < min {
					min = c[v]
				}
			}
			s += min
		}
	}
	Fprint(out, s)
}

func main() { CF1027D(os.Stdin, os.Stdout) }


package main

import (
	"bufio"
	. "fmt"
	"io"
	"os"
)

// github.com/EndlessCheng/codeforces-go
func CF1027D(_r io.Reader, _w io.Writer) {
	in := bufio.NewReader(_r)
	out := bufio.NewWriter(_w)
	defer out.Flush()

	var n, min, s int
	Fscan(in, &n)
	c := make([]int, n)
	for i := range c {
		Fscan(in, &c[i])
	}
	g := make([]int, n)
	deg := make([]int, n)
	for i := range g {
		Fscan(in, &g[i])
		g[i]--
		deg[g[i]]++
	}

	vis := make([]int8, n)
	var f func(v int)
	f = func(v int) {
		if vis[v] == 2 {
			return
		}
		vis[v]++
		if vis[v] == 2 && c[v] < min {
			min = c[v]
		}
		f(g[v])
	}
	for i, d := range deg {
		if d == 0 {
			min = 1e9
			f(i)
			if min < 1e9 {
				s += min
			}
		}
	}
	for i, c := range vis {
		if c == 0 {
			min = 1e9
			f(i)
			if min < 1e9 {
				s += min
			}
		}
	}
	Fprint(out, s)
}

func main() { CF1027D(os.Stdin, os.Stdout) }


package main

import (
	"bufio"
	. "fmt"
	"io"
	"os"
)

// github.com/EndlessCheng/codeforces-go
func CF1027D(_r io.Reader, _w io.Writer) {
	in := bufio.NewReader(_r)
	out := bufio.NewWriter(_w)
	defer out.Flush()

	var n, min, s int
	Fscan(in, &n)
	c := make([]int, n)
	for i := range c {
		Fscan(in, &c[i])
	}
	g := make([]int, n)
	for i := range g {
		Fscan(in, &g[i])
		g[i]--
	}

	vis := make([]int8, n)
	var f func(v int)
	f = func(v int) {
		if vis[v] == 2 || vis[v] == 0 && vis[g[v]] == 2 {
			return
		}
		vis[v]++
		if vis[v] == 2 && c[v] < min {
			min = c[v]
		}
		f(g[v])
	}
	for i, c := range vis {
		if c == 0 {
			min = 1e9
			f(i)
			if min < 1e9 {
				s += min
			}
		}
	}
	Fprint(out, s)
}

func main() { CF1027D(os.Stdin, os.Stdout) }


package main

import(
  "os"
  "bufio"
  "strconv"
  "fmt"
  // "sort"
)

var scanner * bufio.Scanner

func next_int()(result int64){
  if !scanner.Scan() {
    panic("Unable to read next integer. Input has no data remain")
  }
  res, err := strconv.ParseInt(scanner.Text(), 10, 32)
  if err != nil {
    panic(err)
  }
  return res
}

func next_str()(result string){
  if !scanner.Scan() {
    panic("Unable to read next token. Input has no data remain")
  }
  return scanner.Text()
}

func min(a, b int)(int) {
  if a < b {
    return a
  }
  return b;
}

var INF int = 2 * 1000 * 1000 * 1000
var c []int = nil
var next []int = nil
var cost []int = nil
var used []int8 = nil
var stack []int = nil

func check_in_stack(v int)(bool) {
  return (used[v] & (1 << 1)) > 0
}
func invert_in_stack(v int)() {
  used[v] = used[v] ^ (1 << 1);
  return
}
func is_used(v int)(bool){
  return (used[v] & 1) > 0
}
func set_used(v int)(){
  used[v] = used[v] ^ 1;
}

func get_min_cost(v int)(int, bool){
  set_used(v)
  invert_in_stack(v)
  stack = append(stack, v)

  res := INF
  solved_before := false
  if check_in_stack(next[v]) { // cycle found!
    for j := len(stack)-1; j >= 0; j-- {
      res = min(res, c[stack[j]])
      if stack[j] == next[v] {
        break
      }
    }
  } else if is_used(next[v]) { // it was solved before, just extract the answer
    res = cost[next[v]]
    solved_before = true
  } else { // no cycle, not solved before - go deeper
    ch_res, solved_ch := get_min_cost(next[v])
    res = ch_res
    solved_before = solved_ch
  }

  invert_in_stack(v)
  stack = stack[0:len(stack)-1]
  return res, solved_before
}

func main() {

  scanner = bufio.NewScanner(os.Stdin)
  scanner.Split(bufio.ScanWords)

  n := int(next_int());
  c = make([]int, n, n)
  next = make([]int, n, n)
  cost = make([]int, n, n)
  stack = make([]int, 0 , n)
  used = make([]int8, n, n)

  for i := 0; i < n; i++ {
    c[i] = int(next_int());
    used[i] = 0
    cost[i] = INF
  }
  for i := 0; i < n; i++ {
    next[i] = int(next_int() - 1);
  }
  var ans int = 0
  for i := 0; i < n; i++ {
    if 0 == used[i] {
      minc, solved_before := get_min_cost(i)
      if !solved_before {
        ans = ans + minc
      }
    }
  }
  fmt.Println(ans);
  return
}


import sys
sys.setrecursionlimit(1500)

n = input()
c = map(int, raw_input().split())
a = map(int, raw_input().split())

v = [False] * n

def dfsa(x, v):
    if v[x]: return [x]
    v[x] = True
    y = a[x] - 1
    return [x] + dfsa(y, v)

for i in range(n):
    if v[i]: continue
    p = dfsa(i, v)
    j = p.index(p[-1])
    if j < len(p) - 1:
        q = p[j:]
        k = c[q[0]]
        for x in q:
            if c[x] < k: k = c[x]
        for x in q: c[x] = k

def dfsb(x, v, e):
    v[x] = True
    y = a[x] - 1
    if v[y]: return e[y]
    else:
        e[y] = dfsb(y, v, e)
        return e[y]

v = [False] * n
e = range(n)

for i in range(n):
    if v[i]: continue
    e[i] = dfsb(i, v, e)

z = 0
for x in set(e): z += c[x]
print z


import sys
sys.setrecursionlimit(1000000)

n = input()
c = map(int, raw_input().split())
a = map(int, raw_input().split())

v = [False] * n

def dfsa(x, v):
    if v[x]: return [x]
    v[x] = True
    y = a[x] - 1
    return [x] + dfsa(y, v)

for i in range(n):
    if v[i]: continue
    p = dfsa(i, v)
    j = p.index(p[-1])
    if j < len(p) - 1:
        q = p[j:]
        k = c[q[0]]
        for x in q:
            if c[x] < k: k = c[x]
        for x in q: c[x] = k

def dfsb(x, v, e):
    y = a[x] - 1
    if v[y]: return e[x]
    else:
        v[y] = True
        e[y] = dfsb(y, v, e)
        return e[y]

v = [False] * n
e = range(n)

for i in range(n):
    if v[i]: continue

    y = a[i] - 1
    if v[y]:
        v[i] = True
        e[i] = e[y]
    else:
        v[i] = True
        e[i] = dfsb(i, v, e)

z = 0
for x in set(e): z += c[x]
print z


import sys
sys.setrecursionlimit(1500)

n = input()
c = map(int, raw_input().split())
a = map(int, raw_input().split())

v = [False] * n
e = range(n)

def dfs(x):
    y = a[x] - 1
    if v[y]: return e[x]
    else:
        v[y] = True
        e[y] = dfs(y)
        return e[y]

for i in range(n):
    if v[i]: continue

    y = a[i] - 1
    if v[y]:
        v[i] = True
        e[i] = e[y]
    else:
        v[i] = True
        e[i] = dfs(i)

z = 0
for x in set(e): z += c[x]
print z


import sys
sys.setrecursionlimit(1500)

n = input()
c = map(int, raw_input().split())
a = map(int, raw_input().split())

v = [False] * n

def dfsa(x, v):
    if v[x]: return [x]
    v[x] = True
    y = a[x] - 1
    return [x] + dfsa(y, v)

for i in range(n):
    if v[i]: continue
    p = dfsa(i, v)
    j = p.index(p[-1])
    if j < len(p) - 1:
        q = p[j:]
        k = c[q[0]]
        for x in q:
            if c[x] < k: k = c[x]
        for x in q: c[x] = k

def dfsb(x, v, e):
    y = a[x] - 1
    if v[y]: return e[x]
    else:
        v[y] = True
        e[y] = dfsb(y, v, e)
        return e[y]

v = [False] * n
e = range(n)

for i in range(n):
    if v[i]: continue

    y = a[i] - 1
    if v[y]:
        v[i] = True
        e[i] = e[y]
    else:
        v[i] = True
        e[i] = dfsb(i, v, e)

z = 0
for x in set(e): z += c[x]
print z


import sys
sys.setrecursionlimit(1500)

n = input()
c = map(int, raw_input().split())
a = map(int, raw_input().split())

v = [False] * n
for i in range(n):
    if v[i]: continue

    x = i
    p = []
    while True:
        p.append(x)
        if v[x]: break
        v[x] = True
        x = a[x] - 1

    j = p.index(p[-1])
    if j < len(p) - 1:
        q = p[j:]
        k = c[q[0]]
        for x in q:
            if c[x] < k: k = c[x]
        for x in q: c[x] = k

def dfsb(x, v, e):
    v[x] = True
    y = a[x] - 1
    if v[y]: return e[y]
    else:
        e[y] = dfsb(y, v, e)
        return e[y]

v = [False] * n
e = range(n)
for i in range(n):
    if v[i]: continue

    x = i
    p = []
    k = 0
    while True:
        p.append(x)
        v[x] = True
        y = a[x] - 1
        if v[y]:
            k = e[y]
            break
        else: x = y

    for x in p: e[x] = k

z = 0
for x in set(e): z += c[x]
print z


import sys
sys.setrecursionlimit(200001)

n = input()
c = map(int, raw_input().split())
a = map(int, raw_input().split())

v = [False] * n

def dfsa(x, v):
    if v[x]: return [x]
    v[x] = True
    y = a[x] - 1
    return [x] + dfsa(y, v)

for i in range(n):
    if v[i]: continue
    p = dfsa(i, v)
    j = p.index(p[-1])
    if j < len(p) - 1:
        q = p[j:]
        k = c[q[0]]
        for x in q:
            if c[x] < k: k = c[x]
        for x in q: c[x] = k

def dfsb(x, v, e):
    y = a[x] - 1
    if v[y]: return e[x]
    else:
        v[y] = True
        e[y] = dfsb(y, v, e)
        return e[y]

v = [False] * n
e = range(n)

for i in range(n):
    if v[i]: continue

    y = a[i] - 1
    if v[y]:
        v[i] = True
        e[i] = e[y]
    else:
        v[i] = True
        e[i] = dfsb(i, v, e)

z = 0
for x in set(e): z += c[x]
print z


n=input()
vis=[0 for i in range(n+1)]
cost=map(int,raw_input().split())
arr=map(int,raw_input().split())
arr=[0]+arr
cost=[0]+cost
ans=0
for i in range(1,len(arr)):
    temp=i
    while(vis[temp]==0):
        vis[temp]=i
        temp=arr[temp]
    if vis[temp]!=i:
        continue
    mi=cost[temp]
    nex=arr[temp]
    while(nex!=temp):
        mi=min(mi,cost[nex])
        nex=arr[nex]
    ans+=mi
print ans


def dfs1(i,j,c,a):
	b=a[i]
	while(1):
		if i==j:
			break
		b=min(b,a[c[i]])
		i=c[i]
	return b
def dfs(i,c,v,r,a,k):
	v[i]=1
	r[i]=1
	if v[c[i]]==0:
		dfs(c[i],c,v,r,a,k)
	else:
		if r[c[i]]==1:
			k[0]=dfs1(c[i],i,c,a)
	r[i]=0
	return 0
def graph(c,a):
	cost=0
	v=[0]*(len(c))
	r=[0]*(len(c))
	for i in xrange(1,len(c)):
		if v[i]==0:
			k=[0,0]
			dfs(i,c,v,r,a,k)
			cost+=k[0]
	return cost

n=input()
c=map(int,raw_input().split())
a=map(int,raw_input().split())
c.insert(0,0)
a.insert(0,0)
print graph(a,c)


def dfs(i,c,v,r,a,k):
	v[i]=1
	r[i]=1
	if v[c[i]]==0:
		dfs(c[i],c,v,r,a,k)
	else:
		if r[c[i]]==1:
			k[0]=min(a[i],a[c[i]])
	r[i]=0
	return 0
def graph(c,a):
	cost=0
	v=[0]*(len(c))
	r=[0]*(len(c))
	for i in xrange(1,len(c)):
		if v[i]==0:
			k=[0]
			dfs(i,c,v,r,a,k)
			cost+=k[0]
	return cost

n=input()
c=map(int,raw_input().split())
a=map(int,raw_input().split())
c.insert(0,0)
a.insert(0,0)
print graph(a,c)


import sys
raw_input=sys.stdin.readline
def dfs1(i,j,c,a):
	b=a[i]
	while(1):
		if i==j:
			break
		b=min(b,a[c[i]])
		i=c[i]
	return b
def dfs(i,c,v,r,a,k):
	v[i]=1
	r[i]=1
	if v[c[i]]==0:
		dfs(c[i],c,v,r,a,k)
	else:
		if r[c[i]]==1:
			k[0]=dfs1(c[i],i,c,a)
	r[i]=0
	return 0
def graph(c,a):
	cost=0
	v=[0]*(len(c))
	r=[0]*(len(c))
	for i in xrange(1,len(c)):
		if v[i]==0:
			k=[0]
			dfs(i,c,v,r,a,k)
			cost+=k[0]
	return cost

n=input()
c=map(int,raw_input().split())
a=map(int,raw_input().split())
c=[0]+c
a=[0]+a
print graph(a,c)


R=lambda:map(int,raw_input().split())
n=input()
c=R()
a=R()
v=[-1]*n
t=0
for i in range(n):
    x=i
    while v[x]<0:
        v[x]=i
        x=a[x]-1
    if v[x]==i:
        y=x
        z=c[y]
        while a[y]!=x+1:
            y=a[y]-1
            z=min(z,c[y])
        t+=z
print t


from sys import stdin
from collections import *

class graph:
    # initialize graph
    def __init__(self, gdict=None):
        self.gdict = [[] for _ in range(n)]

    # add edge
    def addEdge(self, node1, node2, w=None):
        self.gdict[node1].append(node2)

    def find_SCC(self):
        SCC, S, P, d = [], [], [], 0
        depth, stack = [0] * n, list(range(n))

        while stack:
            # print(stack, S, P)
            node = stack.pop()
            if node < 0:
                if P[-1] == depth[~node]:
                    P.pop()
                    scc = []
                    SCC.append(scc)

                    root = ~node
                    while node != root:
                        node = S.pop()
                        scc.append(node)
                        depth[node] = -1

            elif depth[node] > 0:
                while P[-1] > depth[node]:
                    P.pop()

            elif depth[node] == 0:
                depth[node] = d = d + 1
                P.append(d)
                S.append(node)
                stack.append(~node)
                stack += g.gdict[node]

        return SCC

rints = lambda: [int(x) for x in stdin.readline().split()]
n, c, a = int(input()), rints(), rints()
g = graph()
for i in range(n):
    g.addEdge(i, a[i] - 1)

ans = 0
for cnt in g.find_SCC():
    if len(cnt) > 1 or a[cnt[0]] == cnt[0] + 1:
        ans += min([c[i] for i in cnt])

print(ans)


from sys import stdin
from collections import *

class graph:
    # initialize graph
    def __init__(self, gdict=None):
        self.gdict = [[] for _ in range(n)]

    # add edge
    def addEdge(self, node1, node2, w=None):
        self.gdict[node1].append(node2)

    def find_SCC(self):
        SCC, S, P, d = [], [], [], 0
        depth, stack = [0] * n, list(range(n))

        while stack:
            # print(stack, S, P)
            node = stack.pop()
            if node < 0:
                if P[-1] == depth[~node]:
                    P.pop()
                    scc = []
                    SCC.append(scc)

                    root = ~node
                    while node != root:
                        node = S.pop()
                        scc.append(node)
                        depth[node] = -1

            elif depth[node] > 0:
                while P[-1] > depth[node]:
                    P.pop()

            elif depth[node] == 0:
                depth[node] = d = d + 1
                P.append(d)
                S.append(node)
                stack.append(~node)
                stack += g.gdict[node]

        return SCC[::-1]

rints = lambda: [int(x) for x in stdin.readline().split()]
n, c, a = int(input()), rints(), rints()
g = graph()
for i in range(n):
    g.addEdge(i, a[i] - 1)

ans = 0
for cnt in g.find_SCC():
    if len(cnt) == 1 and a[cnt[0]] == cnt[0] + 1:
        ans += c[cnt[0]]

    elif len(cnt) > 1:
        ans += min([c[i] for i in cnt])

print(ans)


from sys import stdin
from collections import *

class graph:
    # initialize graph
    def __init__(self, gdict=None):
        self.gdict = [[] for _ in range(n+1)]

    # add edge
    def addEdge(self, node1, node2, w=None):
        self.gdict[node1].append(node2)

    def find_SCC(self):
        SCC, S, P, d = [], [], [], 0
        depth, stack = [0] * (n + 1), list(range(1, n + 1))

        while stack:
            # print(stack, S, P)
            node = stack.pop()
            if node < 1:
                if P[-1] == depth[~node]:
                    P.pop()
                    SCC.append([])

                    root = ~node
                    while node != root:
                        node = S.pop()
                        SCC[-1].append(node)
                        depth[node] = -1

            elif depth[node] > 0:
                while P[-1] > depth[node]:
                    P.pop()

            elif depth[node] == 0:
                depth[node] = d = d + 1
                P.append(d)
                S.append(node)
                stack.append(~node)
                stack += g.gdict[node]

        return SCC

rints = lambda: [int(x) for x in stdin.readline().split()]
n, c, a = int(input()), rints(), rints()
g = graph()
for i in range(n):
    g.addEdge(i + 1, a[i])

ans = 0
for cnt in g.find_SCC():
    if len(cnt) > 1 or a[cnt[0] - 1] == cnt[0]:
        ans += min([c[i - 1] for i in cnt])

print(ans)


from sys import stdin
from collections import *

class graph:
    # initialize graph
    def __init__(self, gdict=None):
        self.gdict = [[] for _ in range(n)]

    # add edge
    def addEdge(self, node1, node2, w=None):
        self.gdict[node1].append(node2)

    def find_SCC(self):
        SCC, S, P, d = [], [], [], 0
        depth, stack = [0] * n, list(range(n))

        while stack:
            # print(stack, S, P)
            node = stack.pop()
            if node < 0:
                if P[-1] == depth[~node]:
                    P.pop()
                    SCC.append([])

                    root = ~node
                    while node != root:
                        node = S.pop()
                        SCC[-1].append(node)
                        depth[node] = -1

            elif depth[node] > 0:
                while P[-1] > depth[node]:
                    P.pop()

            elif depth[node] == 0:
                depth[node] = d = d + 1
                P.append(d)
                S.append(node)
                stack.append(~node)
                stack += g.gdict[node]

        return SCC

rints = lambda: [int(x) for x in stdin.readline().split()]
n, c, a = int(input()), rints(), rints()
g = graph()
for i in range(n):
    g.addEdge(i, a[i] - 1)

ans = 0
for cnt in g.find_SCC():
    if len(cnt) > 1 or a[cnt[0]] == cnt[0] + 1:
        ans += min([c[i] for i in cnt])

print(ans)


from sys import *
n = int(stdin.readline())
a = map(int,stdin.readline().split())
b = map(int,stdin.readline().split())
for i in range(n):
    b[i] = b[i]-1
cost = 0
visit = ['c']*n
for i in range(n):
    node = i
    while(visit[node]=='c'):
        visit[node] = i
        node = b[node]

    if(visit[node]==i):
        nex = b[node]
        mini = a[node]
        while(nex != node):
            mini = min(mini,a[nex])
            nex = b[nex]
        cost += mini
stdout.write(str(cost))


import sys
range = xrange
input = sys.stdin.readline

n = int(input())
C = [int(x) for x in input().split()]
A = [int(x)-1 for x in input().split()]

times_found = [0]*n
fixed = [False]*n

cost = 0

for root in range(n):
    if fixed[root]:continue
    node = root

    times_found[node] += 1
    path = [node]
    node = A[node]
    while not fixed[node]:
        if times_found[node]==2:
            break
        path.append(node)
        times_found[node] += 1
        node = A[node]
    else:
        for node in path:
            fixed[node]=True
        continue

    cost += min(C[i] for i in path if times_found[i]==2)

    for node in path:
        fixed[node]=True
print cost


n = input()
c = [0] + map(int, raw_input().strip().split())
a = [0] + map(int, raw_input().strip().split())
ans = 0
isincycle = [0 for i in xrange(n + 1)]
visited = [0 for i in xrange(n + 1)]

cyc = 1

for i in xrange(1, n + 1):
    if visited[i]: continue
    room = i
    while not visited[room]:
        visited[room] = 1
        room = a[room]

    if visited[room] and not isincycle[room]: # means a new cycle discovered
        val = c[room]
        while (not isincycle[room]):
            isincycle[room] = cyc
            room = a[room]
            val = min(val, c[room])
        ans += val

        room = i
        while not isincycle[room]:
            isincycle[room] = cyc
            room = a[room]

        cyc += 1

    room = i
    while not isincycle[room]:
        isincycle[room] = cyc
        room = a[room]

print ans


# Leemos la entrada
n = int(input())
c = [int(x) for x in input().split()]
c.insert(0,0)
a = [int(x) for x in input().split()]
a.insert(0,0)

done = [0]*(n+1) # Para marcar los ciclos
sol = 0
c_i = 0

# Vemos hacia donde va el raton en dependencia de la habitacion o vertice  por donde comienza
for i in range(1,n+1):
    c_i+=2
    cost=0

    # Si es un vertice que ya vimos pasamos a la siguiente iteracion
    if done[i]!=0:
        continue

    # Marcamos todos los vertices que son alcanzables desde el actual
    while done[i]==0:
        done[i]=c_i
        i=a[i]

    # Para ver si este ciclo fue analizado antes
    if done[i]==c_i:

        cost = c[i]
        # Recorremos todo el ciclo donde caimos
        while done[i]==c_i:
            done[i]+=1
            i=a[i]
            # Nos quedamos con el vertice que tiene menor costo
            if c[i]<cost:
                cost=c[i]
    # Sumamos el costo del vertice que tenia menor costo del ciclo en el que estabamos
    sol+=cost

# Pintamos la solucion
print(sol)


n = int(input())

c = list(map(int, input().split()))

a = list(map(lambda x: int(x) - 1, input().split()))

deg_in = [0 for _ in range(n)]

d_in_to_v_set = {i: set() for i in range(n + 1)}

for ai in a:
    deg_in[ai] += 1

for i in range(n):
    d_in_to_v_set[deg_in[i]].add(i)

while d_in_to_v_set[0] != set():
    l = list(d_in_to_v_set[0])
    for u in l:
        d_in_to_v_set[deg_in[a[u]]].remove(a[u])
        d_in_to_v_set[deg_in[a[u]] - 1].add(a[u])
        d_in_to_v_set[0].remove(u)
        deg_in[a[u]] -= 1

p = [0 for _ in range(n)]

for v in d_in_to_v_set[1]:
    p[v] = 1

ans, cur = 0, 10**5

for i in range(n):
    s = i
    cur = 10**5
    while p[s] != 0:
        cur = min(cur, c[s])
        p[s] = 0
        s = a[s]
    ans += cur if cur < 10**5 else 0

print(ans)


# 1027D
import collections
def do():
    n = int(input())
    costs = [int(c) for c in input().split(" ")]
    next = [int(c)-1 for c in input().split(" ")]
    ind = [0] * n
    for i,c in enumerate(next):
        if i != c:
            ind[c] += 1
    seen = [0] * n
    res_seen = [0] * n
    res = 0

    def get(entry):
        m = costs[entry]
        p = entry
        while True:
            if res_seen[p]:
                return 0
            res_seen[p] = 1
            m = min(m, costs[p])
            p = next[p]
            if p == entry:
                break
        return m

    def dfs(i):
        stack = [i]
        seen[i] = 1
        while stack:
            cur = stack.pop()
            nei = next[cur]
            if seen[nei]:
                return get(nei)
            seen[nei] = 1
            stack.append(nei)
        return 0

    for i in range(n):
        if ind[i] == 0:
            res += dfs(i)
    for i in range(n):
        if seen[i] == 0:
            res += dfs(i)
    return res

print(do())