Takahashi will play a game using a piece on an array of squares numbered 1, 2, \cdots, N. Square i has an integer C_i written on it. Also, he is given a permutation of 1, 2, \cdots, N: P_1, P_2, \cdots, P_N.
Now, he will choose one square and place the piece on that square. Then, he will make the following move some number of times between 1 and K (inclusive):
 - In one move, if the piece is now on Square i (1 \leq i \leq N), move it to Square P_i. Here, his score increases by C_{P_i}.
Help him by finding the maximum possible score at the end of the game. (The score is 0 at the beginning of the game.)

-----Constraints-----
 - 2 \leq N \leq 5000
 - 1 \leq K \leq 10^9
 - 1 \leq P_i \leq N
 - P_i \neq i
 - P_1, P_2, \cdots, P_N are all different.
 - -10^9 \leq C_i \leq 10^9
 - All values in input are integers.

-----Input-----
Input is given from Standard Input in the following format:
N K
P_1 P_2 \cdots P_N
C_1 C_2 \cdots C_N

-----Output-----
Print the maximum possible score at the end of the game.

-----Sample Input-----
5 2
2 4 5 1 3
3 4 -10 -8 8

-----Sample Output-----
8

When we start at some square of our choice and make at most two moves, we have the following options:
 - If we start at Square 1, making one move sends the piece to Square 2, after which the score is 4. Making another move sends the piece to Square 4, after which the score is 4 + (-8) = -4.
 - If we start at Square 2, making one move sends the piece to Square 4, after which the score is -8. Making another move sends the piece to Square 1, after which the score is -8 + 3 = -5.
 - If we start at Square 3, making one move sends the piece to Square 5, after which the score is 8. Making another move sends the piece to Square 3, after which the score is 8 + (-10) = -2.
 - If we start at Square 4, making one move sends the piece to Square 1, after which the score is 3. Making another move sends the piece to Square 2, after which the score is 3 + 4 = 7.
 - If we start at Square 5, making one move sends the piece to Square 3, after which the score is -10. Making another move sends the piece to Square 5, after which the score is -10 + 8 = -2.
The maximum score achieved is 8.

Difficulty: MEDIUM

Solutions:
import sys
readline = sys.stdin.readline
readall = sys.stdin.read
ns = lambda : readline().rstrip()
ni = lambda : int(readline().rstrip())
nm = lambda : map(int, readline().split())
nl = lambda : list(map(int, readline().split()))
prn = lambda x: print(*x, sep='\n')

def solve():
	(n, k) = nm()
	p = nl()
	_c = nl()
	c = [0] * n
	for i in range(n):
		p[i] -= 1
		c[i] = _c[p[i]]
	m = 31
	MIN = -(1 << 63)
	vertex = list()
	score = list()
	vertex.append(p)
	score.append(c)
	for a in range(1, m + 1):
		p_ath = [0] * n
		c_ath = [0] * n
		for i in range(n):
			p_ath[i] = vertex[a - 1][vertex[a - 1][i]]
			c_ath[i] = score[a - 1][i] + score[a - 1][vertex[a - 1][i]]
		vertex.append(p_ath)
		score.append(c_ath)
	prv = [[MIN, 0] for _ in range(n)]
	nxt = [[MIN, MIN] for _ in range(n)]
	for b in range(m, -1, -1):
		for i in range(n):
			if k >> b & 1:
				nxt[vertex[b][i]][0] = max(nxt[vertex[b][i]][0], prv[i][0] + score[b][i])
				nxt[vertex[b][i]][1] = max(nxt[vertex[b][i]][1], prv[i][1] + score[b][i])
				nxt[i][0] = max(nxt[i][0], prv[i][0], prv[i][1])
			else:
				nxt[vertex[b][i]][0] = max(nxt[vertex[b][i]][0], prv[i][0] + score[b][i])
				nxt[i][0] = max(nxt[i][0], prv[i][0])
				nxt[i][1] = max(nxt[i][1], prv[i][1])
		(prv, nxt) = (nxt, prv)
	ans = max((max(x) for x in prv))
	if ans == 0:
		ans = max(c)
	print(ans)
	return
solve()


(N, K) = map(int, input().split())
P_list = list(map(int, input().split()))
C_list = list(map(int, input().split()))
checked_list = [0 for _ in range(N)]
min_INF = -1 * 10 ** 10
max_score = min_INF
for i in range(N):
	if checked_list[i] == 1:
		continue
	posit = i
	loop_list = [posit]
	score_list = []
	for j in range(N):
		posit = P_list[posit] - 1
		if j == 0:
			score_list.append(C_list[posit])
		else:
			score_list.append(score_list[-1] + C_list[posit])
		if posit in loop_list:
			break
		loop_list.append(posit)
	len_loop = len(loop_list)
	max_score_list = max(score_list)
	around_score = score_list[-1]
	temp_score_base = 0
	if around_score > 0 and K // len_loop > 0:
		temp_score_base += (K // len_loop - 1) * around_score
	for k in range(len_loop):
		checked_list[loop_list[k]] = 1
		temp_max_score = temp_score_base
		rest_score = min_INF
		if around_score > 0 and K // len_loop > 0:
			rest_score = max(max_score_list, max(score_list[:K % len_loop], default=min_INF) + around_score)
		rest_score = max(max(score_list[:min(K, len_loop)]), rest_score)
		temp_max_score = temp_max_score + rest_score
		max_score = max(max_score, temp_max_score)
		now_score = score_list.pop(0)
		len_score = len(score_list)
		score_list = [score_list[l] - now_score for l in range(len_score)]
		score_list.append(score_list[-1] + now_score)
print(max_score)


import numpy as np

def main():
	(n, k) = list(map(int, input().split()))
	p = [int(i) - 1 for i in input().split()]
	c = [int(i) for i in input().split()]
	seen = set()
	loop_list = []
	for start in range(n):
		v = start
		loop = []
		while v not in seen:
			seen.add(v)
			loop.append(c[v])
			v = p[v]
		seen.add(v)
		if loop:
			loop_list.append(np.array(loop))
	ans = min(c)
	for loop in loop_list:
		loop_len = len(loop)
		loop_num = k // loop_len
		loop_mod = k % loop_len
		loop_sum = sum(loop)
		table = np.zeros((loop_len, loop_len), dtype=int)
		table[0] = loop.cumsum()
		table[:, -1] = loop_sum
		for i in range(loop_len - 1):
			table[i + 1, :-1] = (table[i] - loop[i])[1:]
		ans = max(table[:, :min(loop_len, k)].max(), ans)
		if loop_num > 0:
			ans = max(loop_sum * (loop_num - 1) + table[:, :loop_len].max(), ans)
			if loop_mod > 0:
				ans = max(loop_sum * loop_num + table[:, :loop_mod].max(), ans)
	print(ans)

def __starting_point():
	main()
__starting_point()


from itertools import accumulate

def solve(n, k, ppp, ccc):
	NINF = -10 ** 18
	ans = NINF
	checked = [False] * n
	for s in range(n):
		if checked[s] == True:
			continue
		checked[s] = True
		scores = [ccc[ppp[s]]]
		v = ppp[s]
		while v != s:
			scores.append(ccc[ppp[v]])
			checked[v] = True
			v = ppp[v]
		l = len(scores)
		(d, m) = divmod(k, l)
		loop = sum(scores)
		if d > 0:
			d -= 1
			m += l
		scores += scores * 2
		scores.insert(0, 0)
		acc = list(accumulate(scores))
		tmp = max((max(acc[i + 1:i + m + 1]) - acc[i] for i in range(l)))
		ans = max(ans, tmp, loop * d + tmp)
	return ans
(n, k) = list(map(int, input().split()))
ppp = list(map(int, input().split()))
ppp = [p - 1 for p in ppp]
ccc = list(map(int, input().split()))
print(solve(n, k, ppp, ccc))


from itertools import accumulate
import sys
sys.setrecursionlimit(10 ** 6)
(n, k) = map(int, input().split())
p = list(map(int, input().split()))
c = list(map(int, input().split()))

def dfs(G, v, p):
	seen[v] = True
	sc.append(c[v])
	for nv in G[v]:
		if nv == p:
			continue
		if seen[nv]:
			pos[0] = nv
			return
		dfs(G, nv, v)
		if pos[0] != -1:
			return
G = [[] for _ in range(n)]
for i in range(n):
	G[i].append(p[i] - 1)
seen = [False] * n
ans = -float('inf')
for i in range(n):
	if seen[i] == False:
		pos = [-1]
		sc = []
		dfs(G, i, -1)
		if sc:
			sumsc = sum(sc)
			lenc = len(sc)
			for j in range(lenc):
				if j != 0:
					sc = sc[1:] + [sc[0]]
				ac = list(accumulate(sc))
				if sumsc <= 0:
					ans = max(ans, max(ac[:min(k, lenc)]))
				elif k % lenc == 0:
					ans = max(ans, ac[-1] * (k // lenc - 1) + max(ac))
				else:
					ans = max(ans, ac[-1] * (k // lenc) + max(ac[:k % lenc]))
print(ans)


(n, k) = map(int, input().split())
p = list(map(int, input().split()))
c = list(map(int, input().split()))
ans = -10 ** 18
flag = dict()
for i in range(n):
	if i in flag:
		continue
	cur = i
	accum = []
	flag[cur] = 0
	s = 0
	while flag[cur] < 2:
		cur = p[cur] - 1
		s += c[cur]
		accum.append(s)
		if cur not in flag:
			flag[cur] = 0
		else:
			flag[cur] += 1
	l = len(accum) // 2
	loop = accum[l - 1]
	accum = [0] + accum
	for x in range(1, l + 1):
		if loop <= 0 or k // l < 1:
			ans = max(ans, max(accum[x:x + min(k, l)]) - accum[x - 1])
		else:
			a = max(accum[x:x + l - 1]) - accum[x - 1]
			d = accum[x + l - 1] - accum[x - 1]
			if k % l != 0:
				b = max(accum[x:x + k % l]) - accum[x - 1]
				ans = max(ans, max(k // l * d, k // l * d + b, (k // l - 1) * d + a))
			else:
				b = max(accum[x:x + l - 1]) - accum[x - 1]
				ans = max(ans, max(k // l * d, (k // l - 1) * d + a))
print(ans)


(n, k) = map(int, input().split())
p = [int(x) - 1 for x in input().split()]
c = [int(x) for x in input().split()]
pow_num = 31
point = [[0] * n for i in range(pow_num)]
point_max = [[0] * n for i in range(pow_num)]
posi = [[0] * n for i in range(pow_num)]
c_set = set(c)
if all([i < 0 for i in c_set]):
	print(max(c_set))
else:
	for i in range(pow_num):
		if i == 0:
			for j in range(n):
				posi[i][j] = p[j]
				point[i][j] = c[p[j]]
			continue
		for j in range(n):
			posi[i][j] = posi[i - 1][posi[i - 1][j]]
			point[i][j] = point[i - 1][j] + point[i - 1][posi[i - 1][j]]
	for i in range(pow_num):
		if i == 0:
			for j in range(n):
				point_max[i][j] = point[i][j]
			continue
		for j in range(n):
			point_max[i][j] = max(point_max[i - 1][j], point[i - 1][j] + point_max[i - 1][posi[i - 1][j]])
	power_count = list()
	for i in range(pow_num):
		if k & 1 << i:
			power_count.append(i)
		ans = 0
		for i in range(n):
			next_posi = i
			cumsum_point = 0
			for posi_idx in power_count:
				if ans < cumsum_point + point_max[posi_idx][next_posi]:
					ans = cumsum_point + point_max[posi_idx][next_posi]
				cumsum_point += point[posi_idx][next_posi]
				next_posi = posi[posi_idx][next_posi]
	print(ans)


from collections import Counter
from heapq import heapify, heappop, heappush
from itertools import accumulate

def solve(n, k, ppp, ccc):
	NINF = -10 ** 18
	ans = NINF
	checked = [False] * n
	for s in range(n):
		if checked[s] == True:
			continue
		checked[s] = True
		scores = [ccc[ppp[s]]]
		v = ppp[s]
		while v != s:
			scores.append(ccc[ppp[v]])
			checked[v] = True
			v = ppp[v]
		l = len(scores)
		(d, m) = divmod(k, l)
		loop = sum(scores)
		if d > 0:
			d -= 1
			m += l
		scores += scores * 2
		scores.insert(0, 0)
		acc = list(accumulate(scores))
		base = max(0, loop * d)
		range_max = [-a for a in acc[1:m + 1]]
		available_max = Counter(range_max)
		heapify(range_max)
		for i in range(l):
			while available_max[range_max[0]] == 0:
				heappop(range_max)
			ans = max(ans, base - range_max[0] - acc[i])
			old = -acc[i + 1]
			new = -acc[i + m + 1]
			available_max[old] -= 1
			available_max[new] += 1
			heappush(range_max, new)
	return ans
(n, k) = list(map(int, input().split()))
ppp = list(map(int, input().split()))
ppp = [p - 1 for p in ppp]
ccc = list(map(int, input().split()))
print(solve(n, k, ppp, ccc))


from itertools import accumulate
import sys
sys.setrecursionlimit(10 ** 8)
(n, k) = map(int, input().split())
p = list(map(int, input().split()))
c = list(map(int, input().split()))
p = [i - 1 for i in p]
seen = [False] * n
ans = -float('inf')
for i in range(n):
	if not seen[i]:
		sc = []
		stop = i
		while True:
			seen[i] = True
			sc.append(c[i])
			if p[i] == stop:
				break
			i = p[i]
		lens = len(sc)
		for j in range(lens):
			if j != 0:
				sc = sc[1:] + [sc[0]]
			ac = list(accumulate(sc))
			if sum(sc) <= 0:
				ans = max(ans, max(ac[:min(k, lens)]))
			elif k % lens == 0:
				ans = max(ans, ac[-1] * (k // lens - 1) + max(ac))
			else:
				ans = max(ans, ac[-1] * (k // lens) + max(ac[:k % lens]))
print(ans)


import itertools

def __starting_point():
	(N, K) = list(map(int, input().split()))
	P = [int(p) - 1 for p in input().split()]
	C = list(map(int, input().split()))
	cycleIDs = [-1 for _ in range(N)]
	cycleInfs = []
	cycleID = 0
	procCnt = 0
	for n in range(N):
		v = n
		if cycleIDs[v] != -1:
			continue
		else:
			currentCycleCosts = []
			while True:
				currentCycleCosts.append(C[v])
				cycleIDs[v] = cycleID
				v = P[v]
				if cycleIDs[v] != -1:
					procCnt = K % len(currentCycleCosts)
					if len(currentCycleCosts) + procCnt <= K:
						procCnt += len(currentCycleCosts)
					cycleInfs.append((procCnt, len(currentCycleCosts), currentCycleCosts * 3))
					cycleID += 1
					break
	ans = -10 ** 9
	for (procCnt, currentCycleSize, currentCycleCosts) in cycleInfs:
		loopScore = 0
		if sum(currentCycleCosts) > 0:
			cycleLoopCnt = (K - procCnt) // currentCycleSize
			loopScore = cycleLoopCnt * sum(currentCycleCosts[:currentCycleSize])
		for i in range(currentCycleSize):
			score = max(itertools.accumulate(currentCycleCosts[i:i + procCnt]))
			if ans < score + loopScore:
				ans = score + loopScore
	print(ans)
__starting_point()


import sys
from decimal import Decimal
import math
from itertools import combinations, product, accumulate
import bisect
from collections import Counter, deque, defaultdict
MOD = 10 ** 6 + 7
INF = 10 ** 9
PI = 3.141592653589793

def read_str():
	return sys.stdin.readline().strip()

def read_int():
	return int(sys.stdin.readline().strip())

def read_ints():
	return map(int, sys.stdin.readline().strip().split())

def read_str_list():
	return list(sys.stdin.readline().strip().split())

def read_int_list():
	return list(map(int, sys.stdin.readline().strip().split()))

def lcm(a: int, b: int) -> int:
	return a * b // math.gcd(a, b)

def Main():
	(n, k) = read_ints()
	p = read_int_list()
	c = read_int_list()
	loop_list = []
	visit = [False] * n
	for i in range(n):
		if visit[i]:
			continue
		visit[i] = True
		now = i
		loop_tmp = []
		while True:
			now = p[now] - 1
			visit[now] = True
			loop_tmp.append(c[now])
			if visit[p[now] - 1]:
				loop_tmp.append(c[p[now] - 1])
				break
		loop_list.append(loop_tmp)
	ans = -10 ** 18
	for loop in loop_list:
		length = len(loop)
		score = sum(loop)
		if k > length:
			if score > 0:
				ans = max(ans, k // length * score + search_max_score(loop, k % length, length), (k // length - 1) * score + search_max_score(loop, length, length))
			else:
				ans = max(ans, search_max_score(loop, length, length))
		else:
			ans = max(ans, search_max_score(loop, k, length))
	print(ans)

def search_max_score(loop, rest, length):
	if rest == 0:
		ans = 0
	elif rest == 1:
		ans = max(loop)
	else:
		ans = -10 ** 18
		loop += loop
		for i in range(length):
			tmp = list(accumulate(loop[i:i + rest]))
			ans = max(ans, max(tmp))
	return ans
Main()


from math import inf
from sys import setrecursionlimit
setrecursionlimit(10 ** 4)
(N, K) = map(int, input().split())
P = [0] + list(map(int, input().split()))
C = [0] + list(map(int, input().split()))

class Graph(list):

	def __init__(self, n):
		super().__init__([None] * (n + 1))
		self.directions = P
		self.points = C
		self.loops = []
		self.loopscores = []
		self.search()
		self.evalloop()

	def search(self):
		for i in range(1, len(self)):
			self.history = set()
			self.goto(i)

	def goto(self, i):
		if self[i]:
			return self[i]
		if i in self.history:
			return self.addloop(i)
		self.history.add(i)
		(l, p) = self.goto(self.directions[i])
		if self[i] == None:
			self[i] = (l, p + 1)
		return self[i]

	def addloop(self, j):
		loop = [j]
		k = self.directions[j]
		while j != k:
			loop.append(k)
			k = self.directions[k]
		self.loops.append(loop)
		l = len(self.loops) - 1
		for i in loop:
			self[i] = (l, 0)
		return (l, 0)

	def maxscore(self):
		return max((self.score(self.directions[i], K) for i in range(1, len(self))))

	def score(self, i, k):
		if k == 0:
			return 0
		p = self.points[i]
		i = self.directions[i]
		k -= 1
		if self[i][1] > 0:
			s = self.score(i, k)
			return p + max(0, s)
		n = self[i][0]
		loop = self.loops[n]
		j = loop.index(i)
		base = self.base[n]
		loopscore = base[-1]
		leftmax = self.leftmax[n]
		rightmax = self.rightmax[n]
		length = len(loop)
		(d, m) = divmod(k, length)
		if m == 0:
			s = 0
		elif j + m < length:
			if leftmax[j] < leftmax[j + m]:
				s = leftmax[j + m] - base[j]
			elif rightmax[j + 1] > rightmax[j + m + 1]:
				s = rightmax[j + 1] - base[j]
			else:
				s = max(base[j + 1:j + m + 1]) - base[j]
		else:
			s = max(loopscore + leftmax[j + m - length], rightmax[j + 1]) - base[j]
		if d:
			t = max(loopscore + leftmax[j], rightmax[j + 1]) - base[j]
			return max(0, s, s + loopscore * d, t, t + loopscore * (d - 1)) + p
		else:
			return max(0, s, s + loopscore * d) + p

	def evalloop(self):
		(b, c, d) = ([], [], [])
		for l in self.loops:
			(bb, cc, dd) = ([0], [-inf], [-inf])
			for i in l:
				bb.append(bb[-1] + self.points[i])
			for v in bb:
				cc.append(max(cc[-1], v))
			for v in reversed(bb):
				dd.append(max(dd[-1], v))
			b.append(bb)
			c.append(cc[1:])
			d.append(list(reversed(dd[1:])))
		self.base = b
		self.leftmax = c
		self.rightmax = d
g = Graph(N)
print(g.maxscore())


(N, K) = map(int, input().split())
P = list(map(int, input().split()))
_c = list(map(int, input().split()))
C = [0] * N
for i in range(N):
	P[i] -= 1
	C[i] = _c[P[i]]
m = 31
vertex = list()
score = list()
vertex.append(P)
score.append(C)
for b in range(1, m + 1):
	p_bth = [0] * N
	c_bth = [0] * N
	for i in range(N):
		p_bth[i] = vertex[b - 1][vertex[b - 1][i]]
		c_bth[i] = score[b - 1][i] + score[b - 1][vertex[b - 1][i]]
	vertex.append(p_bth)
	score.append(c_bth)
MIN = -(1 << 63)
prv = [[MIN, 0] for _ in range(N)]
nxt = [[MIN, MIN] for _ in range(N)]
for b in range(m, -1, -1):
	for i in range(N):
		if K >> b & 1:
			nxt[vertex[b][i]][0] = max(nxt[vertex[b][i]][0], prv[i][0] + score[b][i])
			nxt[vertex[b][i]][1] = max(nxt[vertex[b][i]][1], prv[i][1] + score[b][i])
			nxt[i][0] = max(nxt[i][0], prv[i][0], prv[i][1])
		else:
			nxt[vertex[b][i]][0] = max(nxt[vertex[b][i]][0], prv[i][0] + score[b][i])
			nxt[i][0] = max(nxt[i][0], prv[i][0])
			nxt[i][1] = max(nxt[i][1], prv[i][1])
	(prv, nxt) = (nxt, prv)
ans = max((max(x) for x in prv))
if ans == 0:
	ans = max(C)
print(ans)


import numpy as np

def __starting_point():
	(N, K) = list(map(int, input().split()))
	P = [int(p) - 1 for p in input().split()]
	C = list(map(int, input().split()))
	cycleIDs = np.full(N, -1, np.int64)
	cycleInfs = []
	cycleID = 0
	procCnt = 0
	for n in range(N):
		v = n
		if cycleIDs[v] != -1:
			continue
		else:
			currentCycleCosts = []
			while True:
				currentCycleCosts.append(C[v])
				cycleIDs[v] = cycleID
				v = P[v]
				if cycleIDs[v] != -1:
					procCnt = K % len(currentCycleCosts)
					if len(currentCycleCosts) + procCnt <= K:
						procCnt += len(currentCycleCosts)
					cycleInfs.append((procCnt, len(currentCycleCosts), np.array(currentCycleCosts + currentCycleCosts)))
					cycleID += 1
					break
	ans = -10 ** 9
	for (procCnt, currentCycleSize, currentCycleCosts) in cycleInfs:
		loopScore = 0
		if np.sum(currentCycleCosts) > 0:
			cycleLoopCnt = (K - procCnt) // currentCycleSize
			loopScore = cycleLoopCnt * np.sum(currentCycleCosts[:currentCycleSize])
		for i in range(currentCycleSize):
			ans = max(ans, np.roll(currentCycleCosts, i).cumsum()[:procCnt].max() + loopScore)
	print(ans)
__starting_point()


import sys, math

def calcweight_tree(N_vertices, edges, times, inf):
	distance = 0
	passed = [False] * N_vertices
	travel_max = -inf
	for i in range(N_vertices):
		if passed[i] == False:
			distance = 0
			left = i
			cost_sum = 0
			costs = []
			min_distance = inf
			while True:
				dest = edges[left][1]
				cost = edges[dest][0]
				if passed[dest] == False:
					passed[dest] = True
					cost_sum += cost
					costs.append(cost_sum)
					left = dest
					if min_distance > cost:
						min_distance = cost
				else:
					period = len(costs)
					increase_period = cost_sum
					break
			remainder = times % period
			cost_minus = [0]
			for j in range(period - 1):
				cost_minus.append(costs[j])
			if increase_period <= 0:
				costs_last = []
				remainder2 = remainder % period
				for j in range(period):
					costs_last.append(costs[j])
				for j in range(period):
					costs_last.append(costs_last[j] + increase_period)
				maxvalue = -inf
				for j in range(period):
					maxvalue_candidate = max(costs_last[j:j + period])
					if maxvalue_candidate - cost_minus[j] > maxvalue:
						maxvalue = maxvalue_candidate - cost_minus[j]
				travel_max = max(maxvalue, travel_max)
			else:
				costs_last = []
				remainder2 = remainder % period
				times_period = times // period - 1
				add_n = times_period * increase_period
				for j in range(remainder2, period):
					costs_last.append(costs[j] + add_n)
				for j in range(0, remainder2):
					costs_last.append(costs[j] + add_n + increase_period)
				for j in range(period):
					costs_last.append(costs_last[j] + increase_period)
				maxvalue = -inf
				for j in range(period):
					maxvalue_candidate = max(costs_last[j:j + period])
					if maxvalue_candidate - cost_minus[j] > maxvalue:
						maxvalue = maxvalue_candidate - cost_minus[j]
				travel_max = max(maxvalue, travel_max)
	return travel_max

def __starting_point():
	(N, K) = list(map(int, input().strip().split()))
	PList = list(map(int, input().strip().split()))
	CList = list(map(int, input().strip().split()))
	inf = 10 ** 10
	N_vertices = N
	edges3 = []
	costs = []
	for i in range(N):
		edges3.append([CList[i], PList[i] - 1])
	weight = calcweight_tree(N_vertices, edges3, K, inf)
	print(weight)
__starting_point()


from collections import deque
it = lambda : list(map(int, input().strip().split()))

def maximise(L, R, cycle):
	cur = 0
	ans = max(cycle)
	queue = deque([0])
	dp = [0] * (2 * L + 1)
	for (i, num) in enumerate(cycle + cycle):
		j = i + 1
		cur += num
		while queue and j - queue[0] > R:
			queue.popleft()
		if queue:
			ans = max(ans, cur - dp[queue[0]])
		while queue and dp[queue[-1]] >= cur:
			queue.pop()
		queue.append(j)
		dp[j] = cur
	return ans

def get(K, cycle):
	L = len(cycle)
	T = sum(cycle)
	if K > L:
		B = (K - 1) // L
		R = K - B * L
	else:
		B = 0
		R = K
	return max(maximise(L, K, cycle), maximise(L, R, cycle) + max(0, B * T))

def solve():
	(N, K) = it()
	P = it()
	C = it()
	for i in range(N):
		P[i] -= 1
	cycles = []
	seen = [False] * N
	for i in range(N):
		if not seen[i]:
			cycle = []
			first = curr = i
			while True:
				seen[curr] = True
				cycle.append(C[curr])
				curr = P[curr]
				if curr == first:
					break
			cycles.append(cycle)
	ans = float('-inf')
	for cycle in cycles:
		ans = max(ans, get(K, cycle))
	return ans

def __starting_point():
	ans = solve()
	print(ans)
__starting_point()


import itertools
(N, K) = [int(_) for _ in input().split()]
P = [int(_) - 1 for _ in input().split()]
C = [int(_) for _ in input().split()]

class SegmentTree:

	def __init__(self, array, f, ti):
		self.f = f
		self.ti = ti
		self.n = n = 2 ** len(array).bit_length()
		self.dat = dat = [ti] * n + array + [ti] * (n - len(array))
		for i in range(n - 1, 0, -1):
			dat[i] = f(dat[i << 1], dat[i << 1 | 1])

	def update(self, p, v):
		(f, n, dat) = (self.f, self.n, self.dat)
		p += n
		dat[p] = v
		while p > 1:
			p >>= 1
			dat[p] = f(dat[p << 1], dat[p << 1 | 1])

	def operate_right(self, p, v):
		(f, n, dat) = (self.f, self.n, self.dat)
		p += n
		dat[p] = f(dat[p], v)
		while p > 1:
			p >>= 1
			dat[p] = f(dat[p << 1], dat[p << 1 | 1])

	def operate_left(self, p, v):
		(f, n, dat) = (self.f, self.n, self.dat)
		p += n
		dat[p] = f(v, dat[p])
		while p > 1:
			p >>= 1
			dat[p] = f(dat[p << 1], dat[p << 1 | 1])

	def query(self, l, r):
		(f, ti, n, dat) = (self.f, self.ti, self.n, self.dat)
		vl = vr = ti
		l += n
		r += n
		while l < r:
			if l & 1:
				vl = f(vl, dat[l])
				l += 1
			if r & 1:
				r -= 1
				vr = f(dat[r], vr)
			l >>= 1
			r >>= 1
		return f(vl, vr)
ans = -10 ** 20
se = set()
for start in range(N):
	if start in se:
		continue
	now = start
	scores = []
	while True:
		if now in se:
			break
		se.add(now)
		scores += [C[now]]
		now = P[now]
	cyclelen = len(scores)
	cum = list(itertools.accumulate(scores * 2))
	st = SegmentTree(cum, max, -10 ** 20)
	(cycle, residue) = divmod(K, cyclelen)
	ans = max([ans] + [st.query(start2 + 1, start2 + 1 + min(cyclelen, K)) - cum[start2] for start2 in range(cyclelen)])
	if cum[-1] > 0 and cycle > 0:
		v1 = cum[-1] * (cycle - 1) // 2 + max((st.query(start2, start2 + cyclelen + 1) - cum[start2] for start2 in range(cyclelen)))
		v2 = cum[-1] * cycle // 2 + max((st.query(start2, start2 + residue + 1) - cum[start2] for start2 in range(cyclelen)))
		ans = max([ans, v1, v2])
print(ans)


import sys
input = sys.stdin.readline

def main():
	(n, k) = list(map(int, input().split()))
	p = [int(x) - 1 for x in input().split()]
	c = list(map(int, input().split()))
	doubling = [[0] * n for i in range(31)]
	doubling_max = [[0] * n for i in range(31)]
	place = [[0] * n for i in range(31)]
	ans = -1000000000
	for i in range(n):
		sub = c[p[i]]
		if sub >= 0:
			break
		if ans < sub:
			ans = sub
		if i == n - 1:
			print(ans)
			return
	for i in range(31):
		if i == 0:
			for j in range(n):
				doubling[i][j] = c[p[j]]
				place[i][j] = p[j]
			continue
		for j in range(n):
			place[i][j] = place[i - 1][place[i - 1][j]]
			doubling[i][j] = doubling[i - 1][j] + doubling[i - 1][place[i - 1][j]]
	for i in range(31):
		if i == 0:
			for j in range(n):
				doubling_max[i][j] = doubling[i][j]
			continue
		for j in range(n):
			doubling_max[i][j] = max(doubling_max[i - 1][j], doubling[i - 1][j] + doubling_max[i - 1][place[i - 1][j]])
	ans = 0
	judge = []
	key = 0
	while k:
		if k % 2:
			judge.append(key)
		k //= 2
		key += 1
	judge.reverse()
	for i in range(n):
		pl = i
		key = 0
		for j in range(len(judge)):
			if ans < key + doubling_max[judge[j]][pl]:
				ans = key + doubling_max[judge[j]][pl]
			key += doubling[judge[j]][pl]
			pl = place[judge[j]][pl]
	print(ans)

def __starting_point():
	main()
__starting_point()


from itertools import accumulate

def main():
	(n, k) = list(map(int, input().split()))
	P = [int(x) - 1 for x in input().split()]
	C = [int(x) for x in input().split()]
	F = [False] * n
	a = -10 ** 9
	for i in range(n):
		if F[i]:
			continue
		(p, F[i], L) = (i, True, [C[i]])
		while P[p] != i:
			p = P[p]
			F[p] = True
			L.append(C[p])
		(t, l) = (sum(L), len(L))
		s = t * (k // l - 1) if t > 0 else 0
		(m, L) = (-10 ** 9, L * 3)
		u = k % l + l if t > 0 else min(k, l)
		for j in range(l):
			m = max(m, max(accumulate(L[j:j + u])))
		a = max(s + m, a)
	print(a)
main()


import numpy as np
(n, k) = map(int, input().split())
p = list(map(int, input().split()))
c = list(map(int, input().split()))
(cycles, check) = ([], [False] * n)
for pi in p:
	if not check[pi - 1]:
		(curr, cycle) = (pi, [])
		check[pi - 1] = True
		while pi != p[curr - 1]:
			check[curr - 1] = True
			cycle.append(c[curr - 1])
			curr = p[curr - 1]
		check[curr - 1] = True
		cycles.append(cycle + [c[curr - 1]])
scores = []
for cycle in (np.array(cycle) for cycle in cycles):
	for i in range(cycle.size):
		cum = np.roll(cycle, i).cumsum()
		if cum[-1] > 0 and k > cycle.size:
			scores.append(cum[-1] * (k // cycle.size - 1) + np.concatenate([cum, cum[:k % cycle.size] + cum[-1]]).max())
		else:
			scores.append(cum[:min(k, cum.size)].max())
print(max(scores))


from itertools import accumulate
(N, K) = list(map(int, input().split()))
P = list(map(int, input().split()))
C = list(map(int, input().split()))
P = [p - 1 for p in P]
check = [False] * N
ans = -float('inf')
for i in range(N):
	if not check[i]:
		score = []
		stop = i
		while 1:
			check[i] = True
			score.append(C[i])
			if P[i] == stop:
				break
			i = P[i]
		length = len(score)
		for j in range(length):
			if j != 0:
				score = score[1:] + [score[0]]
			ac = list(accumulate(score))
			if sum(score) <= 0:
				ans = max(ans, max(ac[:min(K, length)]))
			elif K % length == 0:
				ans = max(ans, ac[-1] * (K // length - 1) + max(ac))
			else:
				ans = max(ans, ac[-1] * (K // length) + max(ac[:K % length]))
print(ans)


(n, k) = map(int, input().split())
p = list(map(int, input().split()))
_c = list(map(int, input().split()))
c = [0] * n
for i in range(n):
	p[i] -= 1
	c[i] = _c[p[i]]
m = 31
MIN = -(1 << 63)
vertex = list()
score = list()
vertex.append(p)
score.append(c)
for a in range(1, m + 1):
	p_ath = [0] * n
	c_ath = [0] * n
	for i in range(n):
		p_ath[i] = vertex[a - 1][vertex[a - 1][i]]
		c_ath[i] = score[a - 1][i] + score[a - 1][vertex[a - 1][i]]
	vertex.append(p_ath)
	score.append(c_ath)
prv = [[MIN, 0] for _ in range(n)]
nxt = [[MIN, MIN] for _ in range(n)]
for b in range(m, -1, -1):
	for i in range(n):
		if k >> b & 1:
			nxt[vertex[b][i]][0] = max(nxt[vertex[b][i]][0], prv[i][0] + score[b][i])
			nxt[vertex[b][i]][1] = max(nxt[vertex[b][i]][1], prv[i][1] + score[b][i])
			nxt[i][0] = max(nxt[i][0], prv[i][0], prv[i][1])
		else:
			nxt[vertex[b][i]][0] = max(nxt[vertex[b][i]][0], prv[i][0] + score[b][i])
			nxt[i][0] = max(nxt[i][0], prv[i][0])
			nxt[i][1] = max(nxt[i][1], prv[i][1])
	(prv, nxt) = (nxt, prv)
ans = max((max(x) for x in prv))
if ans == 0:
	ans = max(c)
print(ans)


import sys

class SWAG:

	def __init__(self):
		self.fold_l = []
		self.r = []
		self.fold_r = ~(1 << 60)

	def push(self, a):
		if self.fold_r < a:
			self.fold_r = a
		self.r.append(a)

	def pop(self):
		if not self.fold_l:
			self.r.reverse()
			self.fold_l = self.r
			self.r = []
			self.fold_r = ~(1 << 60)
			fold_l = self.fold_l
			for i in range(len(fold_l) - 1):
				if fold_l[i + 1] < fold_l[i]:
					fold_l[i + 1] = fold_l[i]
		self.fold_l.pop()

	def get(self):
		if not self.fold_l:
			return self.fold_r
		elif not self.r:
			return self.fold_l[-1]
		else:
			return max(self.fold_l[-1], self.fold_r)
(n, k) = list(map(int, input().split()))
p = [*list(map(int, input().split()))]
c = [*list(map(int, input().split()))]
for i in range(n):
	p[i] -= 1
if max(c) < 0:
	print(max(c))
	return
ans = 0
used = [False] * n
for i in range(n):
	if used[i]:
		continue
	loop = []
	at = i
	while not used[at]:
		loop.append(c[at])
		used[at] = True
		at = p[at]
	siz = len(loop)
	cusum = [0] + loop * 3
	for i in range(siz * 3):
		cusum[i + 1] += cusum[i]
	sum = max(0, cusum[siz])
	d = k % siz
	swag = SWAG()
	for i in range(d):
		swag.push(cusum[i])
	for i in range(siz):
		swag.push(cusum[d + i])
		ans = max(ans, swag.get() - cusum[i] + sum * (k // siz))
		swag.pop()
	if k < siz:
		continue
	d = k % siz + siz
	swag = SWAG()
	for i in range(d):
		swag.push(cusum[i])
	for i in range(siz):
		swag.push(cusum[d + i])
		ans = max(ans, swag.get() - cusum[i] + sum * (k // siz - 1))
		swag.pop()
print(ans)