Buggy python submission (verdict: Runtime Error):
import itertools
import numpy as np

if __name__ == "__main__":

	N,K = map(int,input().split())
	P = [ int(p)-1 for p in input().split() ]
	C = list(map(int,input().split()))

	# print(P)
	# 一度計算したサイクル情報をキャッシュしておくための配列
	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 )
					# ただし、割り切れる場合も、1サイクル分は処理するものとする
					# (1回以上はやらなければならないのを考慮？)
					if procCnt == 0:
						procCnt = len( currentCycleCosts )

					cycleInfs.append( ( procCnt, np.array( currentCycleCosts ) ) )
					cycleID += 1
					break



	scores = []
	# loopScore = 0
	# procCnt = 0
	for procCnt, currentCycleCosts in cycleInfs:

		# サイクル内でループしてスコアを稼ぐ場合の考慮
		# if np.sum(currentCycleCosts) > 0:
		# 	cycleLoopCnt =  ( K - procCnt ) // currentCycleCosts.size
		# 	loopScore = cycleLoopCnt * np.sum(currentCycleCosts)

		# このサイクルに属する全頂点分をまとめて計算する
		for i in range(currentCycleCosts.size):
			if np.sum(currentCycleCosts) > 0:
				# acc = list(itertools.accumulate( np.roll( currentCycleCosts, i )[:procCnt] ) )
				scores.append( np.roll( currentCycleCosts, i )[:procCnt].cumsum().max() ) + (( K - procCnt ) // currentCycleCosts.size) * np.sum(currentCycleCosts) )
			else:
				scores.append( np.roll( currentCycleCosts, i )[:procCnt].cumsum().max() )


	print(max(scores))


Fixed submission:
# 公式解説を見てからやった
# 複数サイクルでき、1-K回移動可能
# N < 5000?多分、O(N * 2N)くらいで行けそうに見えるが。。。

if __name__ == "__main__":

	N,K = 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 = []


	# print(P)

	ans = -1e10
	cycleID = 0

	for n in range(N):

		v = n
		currentCycleItemCnt = 0
		currentCycleTotal = 0

		if cycleIDs[v] != -1:
			currentCycleItemCnt, currentCycleTotal = cycleInfs[ cycleIDs[v] ]
			# print(currentCycleItemCnt, currentCycleTotal)
		else:
			while True:
				# 全頂点について、属するサイクルを計算する
				currentCycleItemCnt += 1
				currentCycleTotal += C[v]

				v = P[v]
				if v == n:
					# サイクル発見
					cycleInfs.append( (currentCycleItemCnt, currentCycleTotal) )
					cycleID += 1
					break

				# 一応、一度サイクルを計算した頂点については、
				# その頂点の属するサイクルの情報をメモっておく。。。
				cycleIDs[v] = cycleID

		procCnt = 0
		currentCycleSumTmp = 0

		while True:

			# 頂点vにコマが置かれた時の最高スコアを計算し、
			# これまでの最高スコアを上回ったら、これまでの最高スコアを更新する
			procCnt += 1
			currentCycleSumTmp += C[v]
			if K < procCnt:
				break

			cycleLoopCnt = 0
			if procCnt < K and 0 < currentCycleTotal:
				cycleLoopCnt = ( K - procCnt ) // currentCycleItemCnt

			# print("v=", v, "currentCycleSumTmp=", currentCycleSumTmp, procCnt)
			tmp = currentCycleSumTmp + cycleLoopCnt * currentCycleTotal
			ans = max( ans, tmp )

			v = P[v]
			if v == n:
				# サイクル終了
				break

	print(ans)

Buggy python submission (verdict: Time Limit Exceeded):
import itertools
import numpy as np

if __name__ == "__main__":

	N,K = map(int,input().split())
	P = [ int(p)-1 for p in input().split() ]
	C = list(map(int,input().split()))

	# print(P)
	# 一度計算したサイクル情報をキャッシュしておくための配列
	cycleIDs = np.full( N, -1, np.int64 )
	cycleInfs = []
	cycleID = 0

	for n in range(N):

		v = n

		if cycleIDs[v] != -1:
			continue
		else:
			currentCycleItemCnt = 0
			currentCycleCosts = []
			while True:
				# 全頂点について、属するサイクルを計算する
				currentCycleItemCnt += 1
				currentCycleCosts.append( C[v] )
				cycleIDs[v] = cycleID

				v = P[v]
				if v == n:
					# サイクル発見
					cycleInfs.append( (currentCycleItemCnt, np.array( currentCycleCosts ) ) )
					cycleID += 1
					break


	scores = []
	for cycleID in cycleIDs:

		currentCycleItemCnt = cycleInfs[cycleID][0]
		currentCycleCosts = cycleInfs[cycleID][1]
		currentCycleTotalScore = np.sum(currentCycleCosts)

		# ループを含めない最大の処理回数
		procCnt = K % currentCycleItemCnt
		# ただし、割り切れる場合も、1サイクル分は処理するものとする
		# (1回以上はやらなければならないのを考慮？)
		if procCnt == 0:
			procCnt = currentCycleItemCnt

		# サイクル内でループしてスコアを稼ぐ場合の考慮
		loopScore = 0
		if currentCycleTotalScore > 0:
			cycleLoopCnt =  ( K - procCnt ) // currentCycleItemCnt
			loopScore = cycleLoopCnt * currentCycleTotalScore

		# このサイクルに属する全頂点分をまとめて計算する
		for i in range(currentCycleItemCnt):
			# 累積和
			# acc = list(itertools.accumulate( np.roll( currentCycleCosts, i )[:procCnt] ) )
			scores.append( max( itertools.accumulate( np.roll( currentCycleCosts, i )[:procCnt] ) ) + loopScore )

	print(max(scores))


Fixed submission:
# 公式解説を見てからやった
# 複数サイクルでき、1-K回移動可能
# N < 5000?多分、O(N * 2N)くらいで行けそうに見えるが。。。

if __name__ == "__main__":

	N,K = 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 = []


	# print(P)

	ans = -1e10
	cycleID = 0

	for n in range(N):

		v = n
		currentCycleItemCnt = 0
		currentCycleTotal = 0

		if cycleIDs[v] != -1:
			currentCycleItemCnt, currentCycleTotal = cycleInfs[ cycleIDs[v] ]
			# print(currentCycleItemCnt, currentCycleTotal)
		else:
			while True:
				# 全頂点について、属するサイクルを計算する
				currentCycleItemCnt += 1
				currentCycleTotal += C[v]

				v = P[v]
				if v == n:
					# サイクル発見
					cycleInfs.append( (currentCycleItemCnt, currentCycleTotal) )
					cycleID += 1
					break

				# 一応、一度サイクルを計算した頂点については、
				# その頂点の属するサイクルの情報をメモっておく。。。
				cycleIDs[v] = cycleID

		procCnt = 0
		currentCycleSumTmp = 0

		while True:

			# 頂点vにコマが置かれた時の最高スコアを計算し、
			# これまでの最高スコアを上回ったら、これまでの最高スコアを更新する
			procCnt += 1
			currentCycleSumTmp += C[v]
			if K < procCnt:
				break

			cycleLoopCnt = 0
			if procCnt < K and 0 < currentCycleTotal:
				cycleLoopCnt = ( K - procCnt ) // currentCycleItemCnt

			# print("v=", v, "currentCycleSumTmp=", currentCycleSumTmp, procCnt)
			tmp = currentCycleSumTmp + cycleLoopCnt * currentCycleTotal
			ans = max( ans, tmp )

			v = P[v]
			if v == n:
				# サイクル終了
				break

	print(ans)

Buggy python submission (verdict: Time Limit Exceeded):
import itertools
import numpy as np

if __name__ == "__main__":

	N,K = map(int,input().split())
	P = [ int(p)-1 for p in input().split() ]
	C = list(map(int,input().split()))

	# print(P)
	# 一度計算したサイクル情報をキャッシュしておくための配列
	cycleIDs = np.full( N, -1, np.int64 )
	cycleInfs = []

	ans = -10 ** 9
	cycleID = 0

	for n in range(N):

		v = n

		if cycleIDs[v] != -1:
			currentCycleItemCnt, currentCycleTotal = cycleInfs[ cycleIDs[v] ]
			# print(currentCycleItemCnt, currentCycleTotal)
		else:
			currentCycleItemCnt = 0
			currentCycleCosts = []
			while True:
				# 全頂点について、属するサイクルを計算する
				currentCycleItemCnt += 1
				currentCycleCosts.append( C[v] )

				v = P[v]
				if v == n:
					# サイクル発見
					cycleInfs.append( (currentCycleItemCnt, np.array( currentCycleCosts ) ) )
					cycleID += 1
					break

				# 一応、一度サイクルを計算した頂点については、
				# その頂点の属するサイクルの情報をメモっておく。。。
				cycleIDs[v] = cycleID

	scores = []
	for cycleID in cycleIDs:

		currentCycleItemCnt = cycleInfs[cycleID][0]
		currentCycleCosts = cycleInfs[cycleID][1]
		currentCycleTotalScore = np.sum(currentCycleCosts)

		# ループを含めない最大の処理回数
		procCnt = K % currentCycleItemCnt
		# ただし、割り切れる場合も、1サイクル分は処理するものとする
		# (1回以上はやらなければならないのを考慮？)
		if procCnt == 0:
			procCnt = currentCycleItemCnt

		# サイクル内でループしてスコアを稼ぐ場合の考慮
		loopScore = 0
		if currentCycleTotalScore > 0:
			cycleLoopCnt =  ( K - procCnt ) // currentCycleItemCnt
			loopScore = cycleLoopCnt * currentCycleTotalScore

		# このサイクルに属する全頂点分をまとめて計算する
		for i in range(currentCycleItemCnt):
			# 累積和
			# acc = list(itertools.accumulate( np.roll( currentCycleCosts, i )[:procCnt] ) )
			scores.append( max( itertools.accumulate( np.roll( currentCycleCosts, i )[:procCnt] ) ) + loopScore )

	print(max(scores))


Fixed submission:
# 公式解説を見てからやった
# 複数サイクルでき、1-K回移動可能
# N < 5000?多分、O(N * 2N)くらいで行けそうに見えるが。。。

if __name__ == "__main__":

	N,K = 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 = []


	# print(P)

	ans = -1e10
	cycleID = 0

	for n in range(N):

		v = n
		currentCycleItemCnt = 0
		currentCycleTotal = 0

		if cycleIDs[v] != -1:
			currentCycleItemCnt, currentCycleTotal = cycleInfs[ cycleIDs[v] ]
			# print(currentCycleItemCnt, currentCycleTotal)
		else:
			while True:
				# 全頂点について、属するサイクルを計算する
				currentCycleItemCnt += 1
				currentCycleTotal += C[v]

				v = P[v]
				if v == n:
					# サイクル発見
					cycleInfs.append( (currentCycleItemCnt, currentCycleTotal) )
					cycleID += 1
					break

				# 一応、一度サイクルを計算した頂点については、
				# その頂点の属するサイクルの情報をメモっておく。。。
				cycleIDs[v] = cycleID

		procCnt = 0
		currentCycleSumTmp = 0

		while True:

			# 頂点vにコマが置かれた時の最高スコアを計算し、
			# これまでの最高スコアを上回ったら、これまでの最高スコアを更新する
			procCnt += 1
			currentCycleSumTmp += C[v]
			if K < procCnt:
				break

			cycleLoopCnt = 0
			if procCnt < K and 0 < currentCycleTotal:
				cycleLoopCnt = ( K - procCnt ) // currentCycleItemCnt

			# print("v=", v, "currentCycleSumTmp=", currentCycleSumTmp, procCnt)
			tmp = currentCycleSumTmp + cycleLoopCnt * currentCycleTotal
			ans = max( ans, tmp )

			v = P[v]
			if v == n:
				# サイクル終了
				break

	print(ans)

Buggy python submission (verdict: Time Limit Exceeded):
import itertools
import numpy as np

if __name__ == "__main__":

	N,K = map(int,input().split())
	P = [ int(p)-1 for p in input().split() ]
	C = list(map(int,input().split()))

	# print(P)
	# 一度計算したサイクル情報をキャッシュしておくための配列
	cycleIDs = np.full( N, -1, np.int64 )
	cycleInfs = []

	ans = -10 ** 9
	cycleID = 0

	for n in range(N):

		v = n

		if cycleIDs[v] != -1:
			currentCycleItemCnt, currentCycleTotal = cycleInfs[ cycleIDs[v] ]
			# print(currentCycleItemCnt, currentCycleTotal)
		else:
			currentCycleItemCnt = 0
			currentCycleCosts = []
			while True:
				# 全頂点について、属するサイクルを計算する
				currentCycleItemCnt += 1
				currentCycleCosts.append( C[v] )

				v = P[v]
				if v == n:
					# サイクル発見
					cycleInfs.append( (currentCycleItemCnt, currentCycleCosts ) )
					cycleID += 1
					break

				# 一応、一度サイクルを計算した頂点については、
				# その頂点の属するサイクルの情報をメモっておく。。。
				cycleIDs[v] = cycleID

	for cycleID in cycleIDs:

		currentCycleItemCnt = cycleInfs[cycleID][0]
		currentCycleCosts = np.array( cycleInfs[cycleID][1] )
		currentCycleTotalScore = np.sum(currentCycleCosts)

		# ループを含めない最大の処理回数
		procCnt = K % currentCycleItemCnt
		# ただし、割り切れる場合も、1サイクル分は処理するものとする
		# (1回以上はやらなければならないのを考慮？)
		if procCnt == 0:
			procCnt = currentCycleItemCnt
		# procCnt = min( K, procCnt )

		# サイクル内でループしてスコアを稼ぐ場合の考慮
		cycleLoopCnt = 0
		if currentCycleTotalScore > 0:
			# その時、ループが発生した方がスコアが高くなる場合
			# ループ回数を計算
			cycleLoopCnt =  ( K - procCnt ) // currentCycleItemCnt
			# print("K - procCnt=", K - procCnt, "currentCycleItemCnt=", currentCycleItemCnt)
			# print("cycleLoopCnt=", cycleLoopCnt)


		# このサイクル内での最大スコア
		currentCycleMaxScore = -10 ** 9

		# このサイクルに属する全頂点分をまとめて計算する
		# まず、ループが発生しない分まで計算

		for i in range(currentCycleItemCnt):
			# 累積和
			acc = list(itertools.accumulate( np.roll( currentCycleCosts, i )[:procCnt] ) )

			# print(i, acc)#[:procCnt])
			currentCycleMaxScore = max( currentCycleMaxScore, max( acc ) )
		# print("currentCycleMaxScore=",currentCycleMaxScore)


		currentCycleMaxScore += cycleLoopCnt * currentCycleTotalScore
		# print("v=", v, "currentCycleItemCnt=", currentCycleItemCnt, "procCnt, cycleLoopCnt, currentCycleMaxScore,currentCycleTotalScore=", procCnt, cycleLoopCnt, currentCycleMaxScore,currentCycleTotalScore)

		ans = max( ans, currentCycleMaxScore )

	print(ans)


Fixed submission:
# 公式解説を見てからやった
# 複数サイクルでき、1-K回移動可能
# N < 5000?多分、O(N * 2N)くらいで行けそうに見えるが。。。

if __name__ == "__main__":

	N,K = 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 = []


	# print(P)

	ans = -1e10
	cycleID = 0

	for n in range(N):

		v = n
		currentCycleItemCnt = 0
		currentCycleTotal = 0

		if cycleIDs[v] != -1:
			currentCycleItemCnt, currentCycleTotal = cycleInfs[ cycleIDs[v] ]
			# print(currentCycleItemCnt, currentCycleTotal)
		else:
			while True:
				# 全頂点について、属するサイクルを計算する
				currentCycleItemCnt += 1
				currentCycleTotal += C[v]

				v = P[v]
				if v == n:
					# サイクル発見
					cycleInfs.append( (currentCycleItemCnt, currentCycleTotal) )
					cycleID += 1
					break

				# 一応、一度サイクルを計算した頂点については、
				# その頂点の属するサイクルの情報をメモっておく。。。
				cycleIDs[v] = cycleID

		procCnt = 0
		currentCycleSumTmp = 0

		while True:

			# 頂点vにコマが置かれた時の最高スコアを計算し、
			# これまでの最高スコアを上回ったら、これまでの最高スコアを更新する
			procCnt += 1
			currentCycleSumTmp += C[v]
			if K < procCnt:
				break

			cycleLoopCnt = 0
			if procCnt < K and 0 < currentCycleTotal:
				cycleLoopCnt = ( K - procCnt ) // currentCycleItemCnt

			# print("v=", v, "currentCycleSumTmp=", currentCycleSumTmp, procCnt)
			tmp = currentCycleSumTmp + cycleLoopCnt * currentCycleTotal
			ans = max( ans, tmp )

			v = P[v]
			if v == n:
				# サイクル終了
				break

	print(ans)

Buggy python submission (verdict: Time Limit Exceeded):
import itertools
import numpy as np

if __name__ == "__main__":

	N,K = map(int,input().split())
	P = [ int(p)-1 for p in input().split() ]
	C = list(map(int,input().split()))

	# 計算済み
	used = [ False for _ in range(N) ]

	# print(P)
	# 一度計算したサイクル情報を一応キャッシュしておく。。。
	cycleIDs = [ -1 for _ in range(N) ]
	cycleInfs = []

	ans = -10 ** 9
	cycleID = 0

	for n in range(N):

		v = n

		currentCycleItemCnt = 0
		currentCycleCosts = []

		if cycleIDs[v] != -1:
			currentCycleItemCnt, currentCycleTotal = cycleInfs[ cycleIDs[v] ]
			# print(currentCycleItemCnt, currentCycleTotal)
		else:
			while True:
				# 全頂点について、属するサイクルを計算する
				currentCycleItemCnt += 1
				currentCycleCosts.append( C[v] )

				v = P[v]
				if v == n:
					# サイクル発見
					cycleInfs.append( (currentCycleItemCnt, currentCycleCosts ) )
					cycleID += 1
					break

				# 一応、一度サイクルを計算した頂点については、
				# その頂点の属するサイクルの情報をメモっておく。。。
				cycleIDs[v] = cycleID

	for cycleID in cycleIDs:

		currentCycleItemCnt = cycleInfs[cycleID][0]
		currentCycleCosts = cycleInfs[cycleID][1]
		currentCycleTotalScore = sum(currentCycleCosts)

		# ループを含めない最大の処理回数
		procCnt = K % currentCycleItemCnt
		# ただし、割り切れる場合も、1サイクル分は処理するものとする
		# (1回以上はやらなければならないのを考慮？)
		if procCnt == 0:
			procCnt = currentCycleItemCnt
		# procCnt = min( K, procCnt )

		# サイクル内でループしてスコアを稼ぐ場合の考慮
		cycleLoopCnt = 0
		if currentCycleTotalScore > 0:
			# その時、ループが発生した方がスコアが高くなる場合
			# ループ回数を計算
			cycleLoopCnt =  ( K - procCnt ) // currentCycleItemCnt
			# print("K - procCnt=", K - procCnt, "currentCycleItemCnt=", currentCycleItemCnt)
			# print("cycleLoopCnt=", cycleLoopCnt)


		# このサイクル内での最大スコア
		currentCycleMaxScore = -10 ** 9

		# このサイクルに属する全頂点分をまとめて計算する
		# まず、ループが発生しない分まで計算
		npCosts = np.array( currentCycleCosts )

		for i in range(currentCycleItemCnt):
			# 累積和
			acc = list(itertools.accumulate( np.roll( npCosts, i )[:procCnt] ) )

			# print(i, acc)#[:procCnt])
			currentCycleMaxScore = max( currentCycleMaxScore, max( acc ) )
		# print("currentCycleMaxScore=",currentCycleMaxScore)


		currentCycleMaxScore += cycleLoopCnt * currentCycleTotalScore
		# print("v=", v, "currentCycleItemCnt=", currentCycleItemCnt, "procCnt, cycleLoopCnt, currentCycleMaxScore,currentCycleTotalScore=", procCnt, cycleLoopCnt, currentCycleMaxScore,currentCycleTotalScore)

		ans = max( ans, currentCycleMaxScore )

	print(ans)


Fixed submission:
# 公式解説を見てからやった
# 複数サイクルでき、1-K回移動可能
# N < 5000?多分、O(N * 2N)くらいで行けそうに見えるが。。。

if __name__ == "__main__":

	N,K = 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 = []


	# print(P)

	ans = -1e10
	cycleID = 0

	for n in range(N):

		v = n
		currentCycleItemCnt = 0
		currentCycleTotal = 0

		if cycleIDs[v] != -1:
			currentCycleItemCnt, currentCycleTotal = cycleInfs[ cycleIDs[v] ]
			# print(currentCycleItemCnt, currentCycleTotal)
		else:
			while True:
				# 全頂点について、属するサイクルを計算する
				currentCycleItemCnt += 1
				currentCycleTotal += C[v]

				v = P[v]
				if v == n:
					# サイクル発見
					cycleInfs.append( (currentCycleItemCnt, currentCycleTotal) )
					cycleID += 1
					break

				# 一応、一度サイクルを計算した頂点については、
				# その頂点の属するサイクルの情報をメモっておく。。。
				cycleIDs[v] = cycleID

		procCnt = 0
		currentCycleSumTmp = 0

		while True:

			# 頂点vにコマが置かれた時の最高スコアを計算し、
			# これまでの最高スコアを上回ったら、これまでの最高スコアを更新する
			procCnt += 1
			currentCycleSumTmp += C[v]
			if K < procCnt:
				break

			cycleLoopCnt = 0
			if procCnt < K and 0 < currentCycleTotal:
				cycleLoopCnt = ( K - procCnt ) // currentCycleItemCnt

			# print("v=", v, "currentCycleSumTmp=", currentCycleSumTmp, procCnt)
			tmp = currentCycleSumTmp + cycleLoopCnt * currentCycleTotal
			ans = max( ans, tmp )

			v = P[v]
			if v == n:
				# サイクル終了
				break

	print(ans)

Buggy python submission (verdict: Time Limit Exceeded):
import sys
import numpy as np
# from numba import njit

# @njit(cache=True)
def calcCycle(N,K,P,C,cycleIDs,cycleItemCnts,cycleTotalScores):
	cycleID = 0

	for n in range(N):

		v = n
		currentCycleItemCnt = 0
		currentCycleTotal = 0

		if cycleIDs[v] != -1:
			continue
			# print(currentCycleItemCnt, currentCycleTotal)
		else:
			while True:
				# 全頂点について、属するサイクルを計算する
				currentCycleItemCnt += 1
				currentCycleTotal += C[v]

				v = P[v]
				if v == n:
					# サイクル発見
					cycleIDs[v] = cycleID
					cycleItemCnts[cycleID] = currentCycleItemCnt
					cycleTotalScores[cycleID] = currentCycleTotal
					cycleID += 1
					break

				# 一応、一度サイクルを計算した頂点については、
				# その頂点の属するサイクルの情報をメモっておく。。。
				cycleIDs[v] = cycleID

def upd(procCnt,P,C,K,v,ans,currentCycleSumTmp,currentCycleItemCnt,currentCycleTotal):
	currentCycleSumTmp += C[v]

	cycleLoopCnt = 0
	if 0 < currentCycleTotal:
		cycleLoopCnt = ( K - procCnt ) // currentCycleItemCnt

	# print("v=", v, "currentCycleSumTmp=", currentCycleSumTmp, "procCnt, cycleLoopCnt, currentCycleTotal=", procCnt, cycleLoopCnt, currentCycleTotal)
	ans = max( ans, currentCycleSumTmp + cycleLoopCnt * currentCycleTotal )
	v = P[v]

	return (currentCycleSumTmp, ans, v)




def main(N,K,P,C,cycleIDs,cycleItemCnts,cycleTotalScores):

	ans = -1e18

	for n in range(N):

		v = n
		currentCycleItemCnt, currentCycleTotal = cycleItemCnts[ cycleIDs[v] ], cycleTotalScores[ cycleIDs[v] ]

		# procCnt = 0
		currentCycleSumTmp = 0


		for k in range(min(K,currentCycleItemCnt)):
			# 頂点vにコマが置かれた時の最高スコアを計算し、
			# これまでの最高スコアを上回ったら、これまでの最高スコアを更新する
			currentCycleSumTmp, ans, v = upd(k+1,P,C,K,v,ans,currentCycleSumTmp,currentCycleItemCnt,currentCycleTotal)
			# procCnt = k+1
			# currentCycleSumTmp += C[v]

			# cycleLoopCnt = 0
			# if 0 < currentCycleTotal:
			# 	cycleLoopCnt = ( K - procCnt ) // currentCycleItemCnt

			# # print("v=", v, "currentCycleSumTmp=", currentCycleSumTmp, "procCnt, cycleLoopCnt, currentCycleTotal=", procCnt, cycleLoopCnt, currentCycleTotal)
			# ans = max( ans, currentCycleSumTmp + cycleLoopCnt * currentCycleTotal )
			# v = P[v]

	print(int(ans))

if sys.argv[-1]=='ONLINE_JUDGE':
	# from numba import njit
	from numba.pycc import CC
	cc=CC('my_module')
	cc.export('calcCycle','void(i8,i8,i8[:],i8[:],i8[:],i8[:],i8[:])')(calcCycle)
	# cc.export('main','void(i8,i8,i8[:],i8[:],i8[:],i8[:],i8[:])')(main)
	cc.export('upd','UniTuple(i8,3)(i8,i8[:],i8[:],i8,i8,i8,i8,i8,i8)')(upd)
	# main=njit(main, cache=True)
	cc.compile()
	exit(0)
from my_module import upd,calcCycle
# from my_module import calcCycle



if __name__ == "__main__":
	N,K = map(int,input().split())
	P = np.array( input().split(), np.int64 )
	P -= 1
	C = np.array( input().split(), np.int64 )

	# 一度計算したサイクル情報を一応キャッシュしておく。。。
	# あんまり意味なさそう
	cycleIDs = np.full( N, -1, dtype=np.int64 )
	cycleItemCnts = np.full( N, -1, dtype=np.int64 )
	cycleTotalScores = np.full( N, -1, dtype=np.int64 )

	calcCycle(N,K,P,C,cycleIDs,cycleItemCnts,cycleTotalScores)

	# print(cycleItemCnts)


	main(N,K,P,C,cycleIDs,cycleItemCnts,cycleTotalScores)
	#print(ans)




Fixed submission:
# 公式解説を見てからやった
# 複数サイクルでき、1-K回移動可能
# N < 5000?多分、O(N * 2N)くらいで行けそうに見えるが。。。

if __name__ == "__main__":

	N,K = 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 = []


	# print(P)

	ans = -1e10
	cycleID = 0

	for n in range(N):

		v = n
		currentCycleItemCnt = 0
		currentCycleTotal = 0

		if cycleIDs[v] != -1:
			currentCycleItemCnt, currentCycleTotal = cycleInfs[ cycleIDs[v] ]
			# print(currentCycleItemCnt, currentCycleTotal)
		else:
			while True:
				# 全頂点について、属するサイクルを計算する
				currentCycleItemCnt += 1
				currentCycleTotal += C[v]

				v = P[v]
				if v == n:
					# サイクル発見
					cycleInfs.append( (currentCycleItemCnt, currentCycleTotal) )
					cycleID += 1
					break

				# 一応、一度サイクルを計算した頂点については、
				# その頂点の属するサイクルの情報をメモっておく。。。
				cycleIDs[v] = cycleID

		procCnt = 0
		currentCycleSumTmp = 0

		while True:

			# 頂点vにコマが置かれた時の最高スコアを計算し、
			# これまでの最高スコアを上回ったら、これまでの最高スコアを更新する
			procCnt += 1
			currentCycleSumTmp += C[v]
			if K < procCnt:
				break

			cycleLoopCnt = 0
			if procCnt < K and 0 < currentCycleTotal:
				cycleLoopCnt = ( K - procCnt ) // currentCycleItemCnt

			# print("v=", v, "currentCycleSumTmp=", currentCycleSumTmp, procCnt)
			tmp = currentCycleSumTmp + cycleLoopCnt * currentCycleTotal
			ans = max( ans, tmp )

			v = P[v]
			if v == n:
				# サイクル終了
				break

	print(ans)

Buggy python submission (verdict: Runtime Error):
# 公式解説を見てからやった
# 複数サイクルでき、1-K回移動可能
# N < 5000?多分、O(N * 2N)くらいで行けそうに見えるが。。。

if __name__ == "__main__":

	N,K = 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 = []


	# print(P)

	ans = -1e19
	cycleID = 0

	for n in range(N):

		v = n
		currentCycleItemCnt = 0
		currentCycleTotal = 0

		if cycleIDs[v] != -1:
			currentCycleItemCnt, currentCycleTotal = cycleInfs[ cycleIDs[v] ]
			# print(currentCycleItemCnt, currentCycleTotal)
		else:
			while True:
				# 全頂点について、属するサイクルを計算する
				currentCycleItemCnt += 1
				currentCycleTotal += C[v]

				v = P[v]
				if v == n:
					# サイクル発見
					cycleInfs.append( (currentCycleItemCnt, currentCycleTotal) )
					cycleID += 1
					break

				# 一応、一度サイクルを計算した頂点については、
				# その頂点の属するサイクルの情報をメモっておく。。。
				cycleIDs[v] = cycleID

		procCnt = 0
		currentCycleSumTmp = 0

		while True:

			# 頂点vにコマが置かれた時の最高スコアを計算し、
			# これまでの最高スコアを上回ったら、これまでの最高スコアを更新する
			procCnt += 1
			currentCycleSumTmp += C[v]
			if K < procCnt:
				break

			cycleLoopCnt = 0
			if procCnt < K and 0 < currentCycleTotal:
				cycleLoopCnt = ( K - procCnt ) // currentCycleItemCnt

			print("v=", v, "currentCycleSumTmp=", currentCycleSumTmp, "procCnt, cycleLoopCnt, currentCycleTotal=", procCnt, cycleLoopCnt, currentCycleTotal)
			tmp = currentCycleSumTmp + cycleLoopCnt * currentCycleTotal
			ans = max( ans, tmp )

			v = P[v]
			if v == n:
				# サイクル終了
				break

	print(ans)


Fixed submission:
# 公式解説を見てからやった
# 複数サイクルでき、1-K回移動可能
# N < 5000?多分、O(N * 2N)くらいで行けそうに見えるが。。。

if __name__ == "__main__":

	N,K = 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 = []


	# print(P)

	ans = -1e10
	cycleID = 0

	for n in range(N):

		v = n
		currentCycleItemCnt = 0
		currentCycleTotal = 0

		if cycleIDs[v] != -1:
			currentCycleItemCnt, currentCycleTotal = cycleInfs[ cycleIDs[v] ]
			# print(currentCycleItemCnt, currentCycleTotal)
		else:
			while True:
				# 全頂点について、属するサイクルを計算する
				currentCycleItemCnt += 1
				currentCycleTotal += C[v]

				v = P[v]
				if v == n:
					# サイクル発見
					cycleInfs.append( (currentCycleItemCnt, currentCycleTotal) )
					cycleID += 1
					break

				# 一応、一度サイクルを計算した頂点については、
				# その頂点の属するサイクルの情報をメモっておく。。。
				cycleIDs[v] = cycleID

		procCnt = 0
		currentCycleSumTmp = 0

		while True:

			# 頂点vにコマが置かれた時の最高スコアを計算し、
			# これまでの最高スコアを上回ったら、これまでの最高スコアを更新する
			procCnt += 1
			currentCycleSumTmp += C[v]
			if K < procCnt:
				break

			cycleLoopCnt = 0
			if procCnt < K and 0 < currentCycleTotal:
				cycleLoopCnt = ( K - procCnt ) // currentCycleItemCnt

			# print("v=", v, "currentCycleSumTmp=", currentCycleSumTmp, procCnt)
			tmp = currentCycleSumTmp + cycleLoopCnt * currentCycleTotal
			ans = max( ans, tmp )

			v = P[v]
			if v == n:
				# サイクル終了
				break

	print(ans)

Buggy python submission (verdict: Time Limit Exceeded):
import sys
import numpy as np
# from numba import njit

# @njit(cache=True)
def calcCycle(N,K,P,C,cycleIDs,cycleItemCnts,cycleTotalScores):
	cycleID = 0

	for n in range(N):

		v = n
		currentCycleItemCnt = 0
		currentCycleTotal = 0

		if cycleIDs[v] != -1:
			continue
			# print(currentCycleItemCnt, currentCycleTotal)
		else:
			while True:
				# 全頂点について、属するサイクルを計算する
				currentCycleItemCnt += 1
				currentCycleTotal += C[v]

				v = P[v]
				if v == n:
					# サイクル発見
					cycleIDs[v] = cycleID
					cycleItemCnts[cycleID] = currentCycleItemCnt
					cycleTotalScores[cycleID] = currentCycleTotal
					cycleID += 1
					break

				# 一応、一度サイクルを計算した頂点については、
				# その頂点の属するサイクルの情報をメモっておく。。。
				cycleIDs[v] = cycleID


def main(N,K,P,C,cycleIDs,cycleItemCnts,cycleTotalScores):

	ans = -1e19

	for n in range(N):

		v = n
		currentCycleItemCnt, currentCycleTotal = cycleItemCnts[ cycleIDs[v] ], cycleTotalScores[ cycleIDs[v] ]

		procCnt = 0
		currentCycleSumTmp = 0

		for k in range(min(K,currentCycleItemCnt)):
			# 頂点vにコマが置かれた時の最高スコアを計算し、
			# これまでの最高スコアを上回ったら、これまでの最高スコアを更新する
			# numbaにするとこの辺の処理の値が変になってるきがする。。。？
			procCnt = k+1
			# NOTES: C[v]アクセスが異常に重い。。。
			currentCycleSumTmp += C[v]
			# if K < procCnt:
			# 	break

			cycleLoopCnt = 0
			if 0 < currentCycleTotal:
				cycleLoopCnt = int(( K - procCnt ) // currentCycleItemCnt)

			# print("v=", v, "currentCycleSumTmp=", currentCycleSumTmp, "procCnt, cycleLoopCnt, currentCycleTotal=", procCnt, cycleLoopCnt, currentCycleTotal)
			ans = max( ans, currentCycleSumTmp + cycleLoopCnt * currentCycleTotal )

			# if P[v] == n:
				# サイクル終了
				# break
			# NOTES: (多分)通常のpythonだとこの取得だけでTLEする模様。。。
			v = P[v]

	print(int(ans))

if sys.argv[-1]=='ONLINE_JUDGE':
	# from numba import njit
	from numba.pycc import CC
	cc=CC('my_module')
	cc.export('calcCycle','void(i8,i8,i8[:],i8[:],i8[:],i8[:],i8[:])')(calcCycle)
	# cc.export('main','void(i8,i8,i8[:],i8[:],i8[:],i8[:],i8[:])')(main)
	# main=njit(main, cache=True)
	cc.compile()
	exit(0)
# from my_module import main,calcCycle
from my_module import calcCycle



if __name__ == "__main__":
	N,K = map(int,input().split())
	P = np.array( input().split(), np.int64 )
	P -= 1
	C = np.array( input().split(), np.int64 )

	# 一度計算したサイクル情報を一応キャッシュしておく。。。
	# あんまり意味なさそう
	cycleIDs = np.full( N, -1, dtype=np.int64 )
	cycleItemCnts = np.full( N, -1, dtype=np.int64 )
	cycleTotalScores = np.full( N, -1, dtype=np.int64 )

	calcCycle(N,K,P,C,cycleIDs,cycleItemCnts,cycleTotalScores)

	# print(cycleItemCnts)


	main(N,K,P,C,cycleIDs,cycleItemCnts,cycleTotalScores)
	#print(ans)




Fixed submission:
# 公式解説を見てからやった
# 複数サイクルでき、1-K回移動可能
# N < 5000?多分、O(N * 2N)くらいで行けそうに見えるが。。。

if __name__ == "__main__":

	N,K = 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 = []


	# print(P)

	ans = -1e10
	cycleID = 0

	for n in range(N):

		v = n
		currentCycleItemCnt = 0
		currentCycleTotal = 0

		if cycleIDs[v] != -1:
			currentCycleItemCnt, currentCycleTotal = cycleInfs[ cycleIDs[v] ]
			# print(currentCycleItemCnt, currentCycleTotal)
		else:
			while True:
				# 全頂点について、属するサイクルを計算する
				currentCycleItemCnt += 1
				currentCycleTotal += C[v]

				v = P[v]
				if v == n:
					# サイクル発見
					cycleInfs.append( (currentCycleItemCnt, currentCycleTotal) )
					cycleID += 1
					break

				# 一応、一度サイクルを計算した頂点については、
				# その頂点の属するサイクルの情報をメモっておく。。。
				cycleIDs[v] = cycleID

		procCnt = 0
		currentCycleSumTmp = 0

		while True:

			# 頂点vにコマが置かれた時の最高スコアを計算し、
			# これまでの最高スコアを上回ったら、これまでの最高スコアを更新する
			procCnt += 1
			currentCycleSumTmp += C[v]
			if K < procCnt:
				break

			cycleLoopCnt = 0
			if procCnt < K and 0 < currentCycleTotal:
				cycleLoopCnt = ( K - procCnt ) // currentCycleItemCnt

			# print("v=", v, "currentCycleSumTmp=", currentCycleSumTmp, procCnt)
			tmp = currentCycleSumTmp + cycleLoopCnt * currentCycleTotal
			ans = max( ans, tmp )

			v = P[v]
			if v == n:
				# サイクル終了
				break

	print(ans)

Buggy python submission (verdict: Time Limit Exceeded):
import sys
import numpy as np
# from numba import njit

# @njit(cache=True)
def calcCycle(N,K,P,C,cycleIDs,cycleItemCnts,cycleTotalScores):
	cycleID = 0

	for n in range(N):

		v = n
		currentCycleItemCnt = 0
		currentCycleTotal = 0

		if cycleIDs[v] != -1:
			continue
			# print(currentCycleItemCnt, currentCycleTotal)
		else:
			while True:
				# 全頂点について、属するサイクルを計算する
				currentCycleItemCnt += 1
				currentCycleTotal += C[v]

				v = P[v]
				if v == n:
					# サイクル発見
					cycleIDs[v] = cycleID
					cycleItemCnts[cycleID] = currentCycleItemCnt
					cycleTotalScores[cycleID] = currentCycleTotal
					cycleID += 1
					break

				# 一応、一度サイクルを計算した頂点については、
				# その頂点の属するサイクルの情報をメモっておく。。。
				cycleIDs[v] = cycleID


def main(N,K,P,C,cycleIDs,cycleItemCnts,cycleTotalScores):

	ans = -1e19

	for n in range(N):

		v = n
		currentCycleItemCnt, currentCycleTotal = cycleItemCnts[ cycleIDs[v] ], cycleTotalScores[ cycleIDs[v] ]

		procCnt = 0
		currentCycleSumTmp = 0

		for _ in range(currentCycleItemCnt):
			# 頂点vにコマが置かれた時の最高スコアを計算し、
			# これまでの最高スコアを上回ったら、これまでの最高スコアを更新する
			# numbaにするとこの辺の処理の値が変になってるきがする。。。？
			procCnt += 1
			currentCycleSumTmp += C[v]
			if K < procCnt:
				break

			cycleLoopCnt = 0
			if procCnt < K and 0 < currentCycleTotal:
				cycleLoopCnt = int(( K - procCnt ) // currentCycleItemCnt)

			# print("v=", v, "currentCycleSumTmp=", currentCycleSumTmp, "procCnt, cycleLoopCnt, currentCycleTotal=", procCnt, cycleLoopCnt, currentCycleTotal)
			tmp = currentCycleSumTmp + cycleLoopCnt * currentCycleTotal
			ans = max( int(ans), int(tmp) )

			# NOTES: (多分)通常のpythonだとこの取得だけでTLEする模様。。。
			# if P[v] == n:
				# サイクル終了
				# break
			v = P[v]

	print(int(ans))

if sys.argv[-1]=='ONLINE_JUDGE':
	# from numba import njit
	from numba.pycc import CC
	cc=CC('my_module')
	cc.export('calcCycle','void(i8,i8,i8[:],i8[:],i8[:],i8[:],i8[:])')(calcCycle)
	# cc.export('main','void(i8,i8,i8[:],i8[:],i8[:],i8[:],i8[:])')(main)
	# main=njit(main, cache=True)
	cc.compile()
	exit(0)
# from my_module import main,calcCycle
from my_module import calcCycle



if __name__ == "__main__":
	N,K = map(int,input().split())
	P = np.array( input().split(), np.int64 )
	P -= 1
	C = np.array( input().split(), np.int64 )

	# 一度計算したサイクル情報を一応キャッシュしておく。。。
	# あんまり意味なさそう
	cycleIDs = np.full( N, -1, dtype=np.int64 )
	cycleItemCnts = np.full( N, -1, dtype=np.int64 )
	cycleTotalScores = np.full( N, -1, dtype=np.int64 )

	calcCycle(N,K,P,C,cycleIDs,cycleItemCnts,cycleTotalScores)

	# print(cycleItemCnts)


	main(N,K,P,C,cycleIDs,cycleItemCnts,cycleTotalScores)
	#print(ans)




Fixed submission:
# 公式解説を見てからやった
# 複数サイクルでき、1-K回移動可能
# N < 5000?多分、O(N * 2N)くらいで行けそうに見えるが。。。

if __name__ == "__main__":

	N,K = 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 = []


	# print(P)

	ans = -1e10
	cycleID = 0

	for n in range(N):

		v = n
		currentCycleItemCnt = 0
		currentCycleTotal = 0

		if cycleIDs[v] != -1:
			currentCycleItemCnt, currentCycleTotal = cycleInfs[ cycleIDs[v] ]
			# print(currentCycleItemCnt, currentCycleTotal)
		else:
			while True:
				# 全頂点について、属するサイクルを計算する
				currentCycleItemCnt += 1
				currentCycleTotal += C[v]

				v = P[v]
				if v == n:
					# サイクル発見
					cycleInfs.append( (currentCycleItemCnt, currentCycleTotal) )
					cycleID += 1
					break

				# 一応、一度サイクルを計算した頂点については、
				# その頂点の属するサイクルの情報をメモっておく。。。
				cycleIDs[v] = cycleID

		procCnt = 0
		currentCycleSumTmp = 0

		while True:

			# 頂点vにコマが置かれた時の最高スコアを計算し、
			# これまでの最高スコアを上回ったら、これまでの最高スコアを更新する
			procCnt += 1
			currentCycleSumTmp += C[v]
			if K < procCnt:
				break

			cycleLoopCnt = 0
			if procCnt < K and 0 < currentCycleTotal:
				cycleLoopCnt = ( K - procCnt ) // currentCycleItemCnt

			# print("v=", v, "currentCycleSumTmp=", currentCycleSumTmp, procCnt)
			tmp = currentCycleSumTmp + cycleLoopCnt * currentCycleTotal
			ans = max( ans, tmp )

			v = P[v]
			if v == n:
				# サイクル終了
				break

	print(ans)

Buggy python submission (verdict: Time Limit Exceeded):
import sys
import numpy as np
# from numba import njit

# @njit(cache=True)
def calcCycle(N,K,P,C,cycleIDs,cycleItemCnts,cycleTotalScores):
	cycleID = 0

	for n in range(N):

		v = n
		currentCycleItemCnt = 0
		currentCycleTotal = 0

		if cycleIDs[v] != -1:
			continue
			# print(currentCycleItemCnt, currentCycleTotal)
		else:
			while True:
				# 全頂点について、属するサイクルを計算する
				currentCycleItemCnt += 1
				currentCycleTotal += C[v]

				v = P[v]
				if v == n:
					# サイクル発見
					cycleIDs[v] = cycleID
					cycleItemCnts[cycleID] = currentCycleItemCnt
					cycleTotalScores[cycleID] = currentCycleTotal
					cycleID += 1
					break

				# 一応、一度サイクルを計算した頂点については、
				# その頂点の属するサイクルの情報をメモっておく。。。
				cycleIDs[v] = cycleID


def main(N,K,P,C,cycleIDs,cycleItemCnts,cycleTotalScores):

	ans = -1e19

	for n in range(N):

		v = n
		currentCycleItemCnt, currentCycleTotal = cycleItemCnts[ cycleIDs[v] ], cycleTotalScores[ cycleIDs[v] ]

		procCnt = 0
		currentCycleSumTmp = 0

		for _ in range(N):
		# while True:
			# NOTES: (多分)通常のpythonだとこのループだけでTLEする模様。。。

			# 頂点vにコマが置かれた時の最高スコアを計算し、
			# これまでの最高スコアを上回ったら、これまでの最高スコアを更新する
			procCnt += 1
			currentCycleSumTmp += C[v]
			if K < procCnt:
				break

			cycleLoopCnt = 0
			if procCnt < K and 0 < currentCycleTotal:
				cycleLoopCnt = int(( K - procCnt ) // currentCycleItemCnt)

			# print("v=", v, "currentCycleSumTmp=", currentCycleSumTmp, "procCnt, cycleLoopCnt, currentCycleTotal=", procCnt, cycleLoopCnt, currentCycleTotal)
			tmp = currentCycleSumTmp + cycleLoopCnt * currentCycleTotal
			ans = max( int(ans), int(tmp) )

			v = P[v]
			if v == n:
				# サイクル終了
				break

	print(int(ans))

if sys.argv[-1]=='ONLINE_JUDGE':
	# from numba import njit
	from numba.pycc import CC
	cc=CC('my_module')
	cc.export('calcCycle','void(i8,i8,i8[:],i8[:],i8[:],i8[:],i8[:])')(calcCycle)
	# cc.export('main','void(i8,i8,i8[:],i8[:],i8[:],i8[:],i8[:])')(main)
	# main=njit(main, cache=True)
	cc.compile()
	exit(0)
# from my_module import main,calcCycle
from my_module import calcCycle



if __name__ == "__main__":
	N,K = map(int,input().split())
	P = np.array( input().split(), np.int64 )
	P -= 1
	C = np.array( input().split(), np.int64 )

	# 一度計算したサイクル情報を一応キャッシュしておく。。。
	# あんまり意味なさそう
	cycleIDs = np.full( N, -1, dtype=np.int64 )
	cycleItemCnts = np.full( N, -1, dtype=np.int64 )
	cycleTotalScores = np.full( N, -1, dtype=np.int64 )

	calcCycle(N,K,P,C,cycleIDs,cycleItemCnts,cycleTotalScores)

	# print(cycleItemCnts)


	main(N,K,P,C,cycleIDs,cycleItemCnts,cycleTotalScores)
	#print(ans)




Fixed submission:
# 公式解説を見てからやった
# 複数サイクルでき、1-K回移動可能
# N < 5000?多分、O(N * 2N)くらいで行けそうに見えるが。。。

if __name__ == "__main__":

	N,K = 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 = []


	# print(P)

	ans = -1e10
	cycleID = 0

	for n in range(N):

		v = n
		currentCycleItemCnt = 0
		currentCycleTotal = 0

		if cycleIDs[v] != -1:
			currentCycleItemCnt, currentCycleTotal = cycleInfs[ cycleIDs[v] ]
			# print(currentCycleItemCnt, currentCycleTotal)
		else:
			while True:
				# 全頂点について、属するサイクルを計算する
				currentCycleItemCnt += 1
				currentCycleTotal += C[v]

				v = P[v]
				if v == n:
					# サイクル発見
					cycleInfs.append( (currentCycleItemCnt, currentCycleTotal) )
					cycleID += 1
					break

				# 一応、一度サイクルを計算した頂点については、
				# その頂点の属するサイクルの情報をメモっておく。。。
				cycleIDs[v] = cycleID

		procCnt = 0
		currentCycleSumTmp = 0

		while True:

			# 頂点vにコマが置かれた時の最高スコアを計算し、
			# これまでの最高スコアを上回ったら、これまでの最高スコアを更新する
			procCnt += 1
			currentCycleSumTmp += C[v]
			if K < procCnt:
				break

			cycleLoopCnt = 0
			if procCnt < K and 0 < currentCycleTotal:
				cycleLoopCnt = ( K - procCnt ) // currentCycleItemCnt

			# print("v=", v, "currentCycleSumTmp=", currentCycleSumTmp, procCnt)
			tmp = currentCycleSumTmp + cycleLoopCnt * currentCycleTotal
			ans = max( ans, tmp )

			v = P[v]
			if v == n:
				# サイクル終了
				break

	print(ans)

Buggy python submission (verdict: Time Limit Exceeded):
import sys
import numpy as np
# from numba import njit

# @njit(cache=True)
def calcCycle(N,K,P,C,cycleIDs,cycleItemCnts,cycleTotalScores):
	cycleID = 0

	for n in range(N):

		v = n
		currentCycleItemCnt = 0
		currentCycleTotal = 0

		if cycleIDs[v] != -1:
			continue
			# print(currentCycleItemCnt, currentCycleTotal)
		else:
			while True:
				# 全頂点について、属するサイクルを計算する
				currentCycleItemCnt += 1
				currentCycleTotal += C[v]

				v = P[v]
				if v == n:
					# サイクル発見
					cycleIDs[v] = cycleID
					cycleItemCnts[cycleID] = currentCycleItemCnt
					cycleTotalScores[cycleID] = currentCycleTotal
					cycleID += 1
					break

				# 一応、一度サイクルを計算した頂点については、
				# その頂点の属するサイクルの情報をメモっておく。。。
				cycleIDs[v] = cycleID


def main(N,K,P,C,cycleIDs,cycleItemCnts,cycleTotalScores):

	ans = -1e19

	for n in range(N):

		v = n
		currentCycleItemCnt, currentCycleTotal = cycleItemCnts[ cycleIDs[v] ], cycleTotalScores[ cycleIDs[v] ]

		procCnt = 0
		currentCycleSumTmp = 0

		while True:

			# 頂点vにコマが置かれた時の最高スコアを計算し、
			# これまでの最高スコアを上回ったら、これまでの最高スコアを更新する
			procCnt += 1
			currentCycleSumTmp += C[v]
			if K < procCnt:
				break

			cycleLoopCnt = 0
			if procCnt < K and 0 < currentCycleTotal:
				cycleLoopCnt = int(( K - procCnt ) // currentCycleItemCnt)

			# print("v=", v, "currentCycleSumTmp=", currentCycleSumTmp, "procCnt, cycleLoopCnt, currentCycleTotal=", procCnt, cycleLoopCnt, currentCycleTotal)
			tmp = currentCycleSumTmp + cycleLoopCnt * currentCycleTotal
			ans = max( int(ans), int(tmp) )

			v = P[v]
			if v == n:
				# サイクル終了
				break

	print(int(ans))

if sys.argv[-1]=='ONLINE_JUDGE':
	# from numba import njit
	from numba.pycc import CC
	cc=CC('my_module')
	cc.export('calcCycle','void(i8,i8,i8[:],i8[:],i8[:],i8[:],i8[:])')(calcCycle)
	# cc.export('main','void(i8,i8,i8[:],i8[:],i8[:],i8[:],i8[:])')(main)
	# main=njit(main, cache=True)
	cc.compile()
	exit(0)
from my_module import calcCycle



if __name__ == "__main__":
	N,K = map(int,input().split())
	P = np.array( input().split(), np.int64 )
	P -= 1
	C = np.array( input().split(), np.int64 )

	cycleIDs = np.full( N, -1, dtype=np.int64 )
	cycleItemCnts = np.full( N, -1, dtype=np.int64 )
	cycleTotalScores = np.full( N, -1, dtype=np.int64 )

	calcCycle(N,K,P,C,cycleIDs,cycleItemCnts,cycleTotalScores)

	# print(cycleItemCnts)


	main(N,K,P,C,cycleIDs,cycleItemCnts,cycleTotalScores)
	#print(ans)




Fixed submission:
# 公式解説を見てからやった
# 複数サイクルでき、1-K回移動可能
# N < 5000?多分、O(N * 2N)くらいで行けそうに見えるが。。。

if __name__ == "__main__":

	N,K = 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 = []


	# print(P)

	ans = -1e10
	cycleID = 0

	for n in range(N):

		v = n
		currentCycleItemCnt = 0
		currentCycleTotal = 0

		if cycleIDs[v] != -1:
			currentCycleItemCnt, currentCycleTotal = cycleInfs[ cycleIDs[v] ]
			# print(currentCycleItemCnt, currentCycleTotal)
		else:
			while True:
				# 全頂点について、属するサイクルを計算する
				currentCycleItemCnt += 1
				currentCycleTotal += C[v]

				v = P[v]
				if v == n:
					# サイクル発見
					cycleInfs.append( (currentCycleItemCnt, currentCycleTotal) )
					cycleID += 1
					break

				# 一応、一度サイクルを計算した頂点については、
				# その頂点の属するサイクルの情報をメモっておく。。。
				cycleIDs[v] = cycleID

		procCnt = 0
		currentCycleSumTmp = 0

		while True:

			# 頂点vにコマが置かれた時の最高スコアを計算し、
			# これまでの最高スコアを上回ったら、これまでの最高スコアを更新する
			procCnt += 1
			currentCycleSumTmp += C[v]
			if K < procCnt:
				break

			cycleLoopCnt = 0
			if procCnt < K and 0 < currentCycleTotal:
				cycleLoopCnt = ( K - procCnt ) // currentCycleItemCnt

			# print("v=", v, "currentCycleSumTmp=", currentCycleSumTmp, procCnt)
			tmp = currentCycleSumTmp + cycleLoopCnt * currentCycleTotal
			ans = max( ans, tmp )

			v = P[v]
			if v == n:
				# サイクル終了
				break

	print(ans)

Buggy python submission (verdict: Time Limit Exceeded):
import sys
import numpy as np

# 公式解説を見てからやった
# 複数サイクルでき、1-K回移動可能
# N < 5000?多分、O(N * 2N)くらいで行けそうに見えるが。。。

def main(N,K,P,C):


	# 一度計算したサイクル情報を一応キャッシュしておく。。。
	# あんまり意味なさそう
	cycleIDs = np.full( N, -1, dtype=np.int64 )
	cycleInfs = []


	# print(P)

	ans = -1e19
	cycleID = 0

	for n in range(N):

		v = n
		currentCycleItemCnt = 0
		currentCycleTotal = 0

		if cycleIDs[v] != -1:
			currentCycleItemCnt, currentCycleTotal = cycleInfs[ cycleIDs[v] ]
			# print(currentCycleItemCnt, currentCycleTotal)
		else:
			while True:
				# 全頂点について、属するサイクルを計算する
				currentCycleItemCnt += 1
				currentCycleTotal += C[v]

				v = P[v]
				if v == n:
					# サイクル発見
					cycleInfs.append( (currentCycleItemCnt, currentCycleTotal) )
					cycleID += 1
					break

				# 一応、一度サイクルを計算した頂点については、
				# その頂点の属するサイクルの情報をメモっておく。。。
				cycleIDs[v] = cycleID

		procCnt = 0
		currentCycleSumTmp = 0

		while True:

			# 頂点vにコマが置かれた時の最高スコアを計算し、
			# これまでの最高スコアを上回ったら、これまでの最高スコアを更新する
			procCnt += 1
			currentCycleSumTmp += C[v]
			if K < procCnt:
				break

			cycleLoopCnt = 0
			if procCnt < K and 0 < currentCycleTotal:
				cycleLoopCnt = int(( K - procCnt ) // currentCycleItemCnt)

			# print("v=", v, "currentCycleSumTmp=", currentCycleSumTmp, procCnt)
			tmp = currentCycleSumTmp + cycleLoopCnt * currentCycleTotal
			ans = max( int(ans), int(tmp) )

			v = P[v]
			if v == n:
				# サイクル終了
				break

	print(int(ans))


if __name__ == "__main__":
	N,K = map(int,input().split())
	P = np.array( input().split(), np.int64 )
	P -= 1
	C = np.array( input().split(), np.int64 )

	main(N,K,P,C)
	#print(ans)




Fixed submission:
# 公式解説を見てからやった
# 複数サイクルでき、1-K回移動可能
# N < 5000?多分、O(N * 2N)くらいで行けそうに見えるが。。。

if __name__ == "__main__":

	N,K = 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 = []


	# print(P)

	ans = -1e10
	cycleID = 0

	for n in range(N):

		v = n
		currentCycleItemCnt = 0
		currentCycleTotal = 0

		if cycleIDs[v] != -1:
			currentCycleItemCnt, currentCycleTotal = cycleInfs[ cycleIDs[v] ]
			# print(currentCycleItemCnt, currentCycleTotal)
		else:
			while True:
				# 全頂点について、属するサイクルを計算する
				currentCycleItemCnt += 1
				currentCycleTotal += C[v]

				v = P[v]
				if v == n:
					# サイクル発見
					cycleInfs.append( (currentCycleItemCnt, currentCycleTotal) )
					cycleID += 1
					break

				# 一応、一度サイクルを計算した頂点については、
				# その頂点の属するサイクルの情報をメモっておく。。。
				cycleIDs[v] = cycleID

		procCnt = 0
		currentCycleSumTmp = 0

		while True:

			# 頂点vにコマが置かれた時の最高スコアを計算し、
			# これまでの最高スコアを上回ったら、これまでの最高スコアを更新する
			procCnt += 1
			currentCycleSumTmp += C[v]
			if K < procCnt:
				break

			cycleLoopCnt = 0
			if procCnt < K and 0 < currentCycleTotal:
				cycleLoopCnt = ( K - procCnt ) // currentCycleItemCnt

			# print("v=", v, "currentCycleSumTmp=", currentCycleSumTmp, procCnt)
			tmp = currentCycleSumTmp + cycleLoopCnt * currentCycleTotal
			ans = max( ans, tmp )

			v = P[v]
			if v == n:
				# サイクル終了
				break

	print(ans)

Buggy python submission (verdict: Time Limit Exceeded):
import numpy as np

# 公式解説を見てからやった
# 複数サイクルでき、1-K回移動可能
# N < 5000?多分、O(N * 2N)くらいで行けそうに見えるが。。。

if __name__ == "__main__":

	N,K = map(int,input().split())
	P = np.array( input().split(), int )
	P -= 1
	C = np.array( input().split(), int )


	# 一度計算したサイクル情報を一応キャッシュしておく。。。
	# あんまり意味なさそう
	cycleIDs = np.full( N, -1, int )
	cycleInfs = []


	# print(P)

	ans = -1e10
	cycleID = 0

	for n in range(N):

		v = n
		currentCycleItemCnt = 0
		currentCycleTotal = 0

		if cycleIDs[v] != -1:
			currentCycleItemCnt, currentCycleTotal = cycleInfs[ cycleIDs[v] ]
			# print(currentCycleItemCnt, currentCycleTotal)
		else:
			while True:
				# 全頂点について、属するサイクルを計算する
				currentCycleItemCnt += 1
				currentCycleTotal += C[v]

				v = P[v]
				if v == n:
					# サイクル発見
					cycleInfs.append( (currentCycleItemCnt, currentCycleTotal) )
					cycleID += 1
					break

				# 一応、一度サイクルを計算した頂点については、
				# その頂点の属するサイクルの情報をメモっておく。。。
				cycleIDs[v] = cycleID

		procCnt = 0
		currentCycleSumTmp = 0

		while True:

			# 頂点vにコマが置かれた時の最高スコアを計算し、
			# これまでの最高スコアを上回ったら、これまでの最高スコアを更新する
			procCnt += 1
			currentCycleSumTmp += C[v]
			if K < procCnt:
				break

			cycleLoopCnt = 0
			if procCnt < K and 0 < currentCycleTotal:
				cycleLoopCnt = ( K - procCnt ) // currentCycleItemCnt

			# print("v=", v, "currentCycleSumTmp=", currentCycleSumTmp, procCnt)
			tmp = currentCycleSumTmp + cycleLoopCnt * currentCycleTotal
			ans = max( ans, tmp )

			v = P[v]
			if v == n:
				# サイクル終了
				break

	print(ans)


Fixed submission:
# 公式解説を見てからやった
# 複数サイクルでき、1-K回移動可能
# N < 5000?多分、O(N * 2N)くらいで行けそうに見えるが。。。

if __name__ == "__main__":

	N,K = 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 = []


	# print(P)

	ans = -1e10
	cycleID = 0

	for n in range(N):

		v = n
		currentCycleItemCnt = 0
		currentCycleTotal = 0

		if cycleIDs[v] != -1:
			currentCycleItemCnt, currentCycleTotal = cycleInfs[ cycleIDs[v] ]
			# print(currentCycleItemCnt, currentCycleTotal)
		else:
			while True:
				# 全頂点について、属するサイクルを計算する
				currentCycleItemCnt += 1
				currentCycleTotal += C[v]

				v = P[v]
				if v == n:
					# サイクル発見
					cycleInfs.append( (currentCycleItemCnt, currentCycleTotal) )
					cycleID += 1
					break

				# 一応、一度サイクルを計算した頂点については、
				# その頂点の属するサイクルの情報をメモっておく。。。
				cycleIDs[v] = cycleID

		procCnt = 0
		currentCycleSumTmp = 0

		while True:

			# 頂点vにコマが置かれた時の最高スコアを計算し、
			# これまでの最高スコアを上回ったら、これまでの最高スコアを更新する
			procCnt += 1
			currentCycleSumTmp += C[v]
			if K < procCnt:
				break

			cycleLoopCnt = 0
			if procCnt < K and 0 < currentCycleTotal:
				cycleLoopCnt = ( K - procCnt ) // currentCycleItemCnt

			# print("v=", v, "currentCycleSumTmp=", currentCycleSumTmp, procCnt)
			tmp = currentCycleSumTmp + cycleLoopCnt * currentCycleTotal
			ans = max( ans, tmp )

			v = P[v]
			if v == n:
				# サイクル終了
				break

	print(ans)

Buggy python submission (verdict: Time Limit Exceeded):
# 公式解説を見てからやった
# 複数サイクルでき、1-K回移動可能
# N < 5000?多分、O(N * 2N)くらいで行けそうに見えるが。。。

if __name__ == "__main__":

	N,K = 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 = []


	# print(P)

	ans = -1e10
	cycleID = 0

	for n in range(N):

		v = n
		currentCycleItemCnt = 0
		currentCycleTotal = 0

		if cycleIDs[v] != -1:
			currentCycleItemCnt, currentCycleTotal = cycleInfs[ cycleIDs[v] ]
			# print(currentCycleItemCnt, currentCycleTotal)
		else:
			while True:
				# 全頂点について、属するサイクルを計算する
				currentCycleItemCnt += 1
				currentCycleTotal += C[v]

				v = P[v]
				if v == n:
					# サイクル発見
					cycleInfs.append( (currentCycleItemCnt, currentCycleTotal) )
					cycleID += 1
					break

				# 一応、一度サイクルを計算した頂点については、
				# その頂点の属するサイクルの情報をメモっておく。。。
				cycleIDs[v] = cycleID

		procCnt = 0
		currentCycleSumTmp = 0

		while True:

			# 頂点vにコマが置かれた時の最高スコアを計算し、
			# これまでの最高スコアを上回ったら、これまでの最高スコアを更新する
			procCnt += 1
			currentCycleSumTmp += C[v]
			if K < procCnt:
				break

			cycleLoopCnt = 0
			if procCnt < K and 0 < currentCycleTotal:
				cycleLoopCnt = ( K - procCnt ) // currentCycleItemCnt

			# print("v=", v, "currentCycleSumTmp=", currentCycleSumTmp, procCnt)
			tmp = currentCycleSumTmp + cycleLoopCnt * currentCycleTotal
			ans = max( ans, tmp )

			v = P[v]
			if v == n:
				# サイクル終了
				break

	print(ans)


Fixed submission:
# 公式解説を見てからやった
# 複数サイクルでき、1-K回移動可能
# N < 5000?多分、O(N * 2N)くらいで行けそうに見えるが。。。

if __name__ == "__main__":

	N,K = 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 = []


	# print(P)

	ans = -1e10
	cycleID = 0

	for n in range(N):

		v = n
		currentCycleItemCnt = 0
		currentCycleTotal = 0

		if cycleIDs[v] != -1:
			currentCycleItemCnt, currentCycleTotal = cycleInfs[ cycleIDs[v] ]
			# print(currentCycleItemCnt, currentCycleTotal)
		else:
			while True:
				# 全頂点について、属するサイクルを計算する
				currentCycleItemCnt += 1
				currentCycleTotal += C[v]

				v = P[v]
				if v == n:
					# サイクル発見
					cycleInfs.append( (currentCycleItemCnt, currentCycleTotal) )
					cycleID += 1
					break

				# 一応、一度サイクルを計算した頂点については、
				# その頂点の属するサイクルの情報をメモっておく。。。
				cycleIDs[v] = cycleID

		procCnt = 0
		currentCycleSumTmp = 0

		while True:

			# 頂点vにコマが置かれた時の最高スコアを計算し、
			# これまでの最高スコアを上回ったら、これまでの最高スコアを更新する
			procCnt += 1
			currentCycleSumTmp += C[v]
			if K < procCnt:
				break

			cycleLoopCnt = 0
			if procCnt < K and 0 < currentCycleTotal:
				cycleLoopCnt = ( K - procCnt ) // currentCycleItemCnt

			# print("v=", v, "currentCycleSumTmp=", currentCycleSumTmp, procCnt)
			tmp = currentCycleSumTmp + cycleLoopCnt * currentCycleTotal
			ans = max( ans, tmp )

			v = P[v]
			if v == n:
				# サイクル終了
				break

	print(ans)

Buggy python submission (verdict: Time Limit Exceeded):
# 公式解説を見てからやった
# 複数サイクルでき、1-K回移動可能
# N < 5000?多分、O(N * 2N)くらいで行けそうに見えるが。。。

if __name__ == "__main__":

	N,K = map(int,input().split())
	P = [ int(p)-1 for p in input().split() ]
	C = list(map(int,input().split()))

	# print(P)

	ans = -1e10

	for n in range(N):

		v = n
		currentCycleItemCnt = 0
		currentCycleTotal = 0

		while True:
			# 全頂点について、属するサイクルを計算する
			currentCycleItemCnt += 1
			currentCycleTotal += C[v]

			v = P[v]
			if v == n:
				# サイクル発見
				break

		procCnt = 0
		currentCycleSumTmp = 0

		while True:

			# 頂点vにコマが置かれた時の最高スコアを計算し、
			# これまでの最高スコアを上回ったら、これまでの最高スコアを更新する
			procCnt += 1
			currentCycleSumTmp += C[v]
			if K < procCnt:
				break

			cycleLoopCnt = 0
			if procCnt < K and 0 < currentCycleTotal:
				cycleLoopCnt = ( K - procCnt ) // currentCycleItemCnt

			# print("v=", v, "currentCycleSumTmp=", currentCycleSumTmp, procCnt)
			tmp = currentCycleSumTmp + cycleLoopCnt * currentCycleTotal
			ans = max( ans, tmp )

			v = P[v]
			if v == n:
				# サイクル終了
				break

	print(ans)


Fixed submission:
# 公式解説を見てからやった
# 複数サイクルでき、1-K回移動可能
# N < 5000?多分、O(N * 2N)くらいで行けそうに見えるが。。。

if __name__ == "__main__":

	N,K = 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 = []


	# print(P)

	ans = -1e10
	cycleID = 0

	for n in range(N):

		v = n
		currentCycleItemCnt = 0
		currentCycleTotal = 0

		if cycleIDs[v] != -1:
			currentCycleItemCnt, currentCycleTotal = cycleInfs[ cycleIDs[v] ]
			# print(currentCycleItemCnt, currentCycleTotal)
		else:
			while True:
				# 全頂点について、属するサイクルを計算する
				currentCycleItemCnt += 1
				currentCycleTotal += C[v]

				v = P[v]
				if v == n:
					# サイクル発見
					cycleInfs.append( (currentCycleItemCnt, currentCycleTotal) )
					cycleID += 1
					break

				# 一応、一度サイクルを計算した頂点については、
				# その頂点の属するサイクルの情報をメモっておく。。。
				cycleIDs[v] = cycleID

		procCnt = 0
		currentCycleSumTmp = 0

		while True:

			# 頂点vにコマが置かれた時の最高スコアを計算し、
			# これまでの最高スコアを上回ったら、これまでの最高スコアを更新する
			procCnt += 1
			currentCycleSumTmp += C[v]
			if K < procCnt:
				break

			cycleLoopCnt = 0
			if procCnt < K and 0 < currentCycleTotal:
				cycleLoopCnt = ( K - procCnt ) // currentCycleItemCnt

			# print("v=", v, "currentCycleSumTmp=", currentCycleSumTmp, procCnt)
			tmp = currentCycleSumTmp + cycleLoopCnt * currentCycleTotal
			ans = max( ans, tmp )

			v = P[v]
			if v == n:
				# サイクル終了
				break

	print(ans)