Problem:
 Score : 400 points    Problem Statement 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 1 5 2
2 4 5 1 3
3 4 -10 -8 8      Sample Output 1 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 .       Sample Input 2 2 3
2 1
10 -7      Sample Output 2 13       Sample Input 3 3 3
3 1 2
-1000 -2000 -3000      Sample Output 3 -1000  We have to make at least one move.       Sample Input 4 10 58
9 1 6 7 8 4 3 2 10 5
695279662 988782657 -119067776 382975538 -151885171 -177220596 -169777795 37619092 389386780 980092719      Sample Output 4 29507023469  The absolute value of the answer may be enormous.

Solution (Python):
import sys
import numpy as np







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


	
	
	cycleIDs = np.full( N, -1, dtype=np.int64 )
	cycleInfs = []


	

	cycleID = 0

	for n in range(N):

		v = n
		currentCycleItemCnt = 0
		currentCycleTotal = 0

		if cycleIDs[v] != -1:
			currentCycleItemCnt, currentCycleTotal = cycleInfs[ cycleIDs[v] ]
			
		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:

			
			
			procCnt += 1
			currentCycleSumTmp += C[v]
			if K < procCnt:
				break

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

			
			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.pycc import CC
	cc=CC('my_module')
	cc.export('main','void(i8,i8,i8[:],i8[:],i8)')(main)
	
	cc.compile()
	exit(0)
from my_module import main



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 )

	ans = -1e18	
	main(N,K,P,C,ans)

Solution (Python):
import sys
import numpy as np



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
			
		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(P,C,K,v,ans,currentCycleItemCnt,currentCycleTotal):

	
	currentCycleSumTmp = 0

	for k in range(min(K,currentCycleItemCnt)):

		
		

		procCnt = k+1
		currentCycleSumTmp += C[v]

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

		
		ans = max( ans, currentCycleSumTmp + cycleLoopCnt * currentCycleTotal )
		v = P[v]

	return ans





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

	for n in range(N):

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

		
		currentCycleSumTmp = 0
		for k in range(min(K,currentCycleItemCnt)):

			procCnt = k+1
			currentCycleSumTmp += C[v]

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

			
			ans = max( ans, currentCycleSumTmp + cycleLoopCnt * currentCycleTotal )
			v = P[v]


	print(int(ans))

if sys.argv[-1]=='ONLINE_JUDGE':
	
	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[:],i8[:])')(main)
	
	
	
	cc.compile()
	exit(0)

from my_module import main,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)

	

	ans = -1e18
	main(ans,N,K,P,C,cycleIDs,cycleItemCnts,cycleTotalScores)

Solution (Python):
import sys
import numpy as np



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
			
		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(P,C,K,v,ans,currentCycleItemCnt,currentCycleTotal):

	
	currentCycleSumTmp = 0

	for k in range(min(K,currentCycleItemCnt)):

		
		

		procCnt = k+1
		currentCycleSumTmp += C[v]

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

		
		ans = max( ans, currentCycleSumTmp + cycleLoopCnt * currentCycleTotal )
		v = P[v]

	return ans





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] ]

		ans=upd(P,C,K,v,ans,currentCycleItemCnt,currentCycleTotal)
		
		

		
		

		
		
		

		
		
		


	print(int(ans))

if sys.argv[-1]=='ONLINE_JUDGE':
	
	from numba.pycc import CC
	cc=CC('my_module')
	cc.export('calcCycle','void(i8,i8,i8[:],i8[:],i8[:],i8[:],i8[:])')(calcCycle)
	
	cc.export('upd','i8(i8[:],i8[:],i8,i8,i8,i8,i8)')(upd)
	
	
	cc.compile()
	exit(0)
from my_module import upd,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)

	


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

Solution (Python):
import sys
import numpy as np



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
			
		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(P,C,K,v,ans,currentCycleItemCnt,currentCycleTotal):

	
	currentCycleSumTmp = 0

	for k in range(min(K,currentCycleItemCnt)):

		
		

		procCnt = k+1
		currentCycleSumTmp += C[v]

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

		
		ans = max( ans, currentCycleSumTmp + cycleLoopCnt * currentCycleTotal )
		v = P[v]

	return ans





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] ]

		ans=upd(P,C,K,v,ans,currentCycleItemCnt,currentCycleTotal)
			
			

			
			
			

			
			
			

	print(int(ans))

if sys.argv[-1]=='ONLINE_JUDGE':
	
	from numba.pycc import CC
	cc=CC('my_module')
	cc.export('calcCycle','void(i8,i8,i8[:],i8[:],i8[:],i8[:],i8[:])')(calcCycle)
	
	cc.export('upd','i8(i8[:],i8[:],i8,i8,i8,i8,i8)')(upd)
	
	
	cc.compile()
	exit(0)
from my_module import upd,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)

	


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

Solution (Python):
n, k = map(int, input().split())
p = list(map(int, input().split()))
c = list(map(int, input().split()))

lastans = -1e20

for i in range(n):
    now = p[i] - 1 
    score = [c[now]]
    while True:
        now = p[now] - 1
        score.append(score[-1] + c[now])
        if now == i:
            break
    loopsum = score[-1]
    looplen = len(score)

    if looplen >= k:
        ans = max(score[:k])
    elif loopsum <= 0:
        ans = max(score)
    else:
        loopnum = k//looplen
        loopnum_mod = k % looplen
        ans1 = loopsum * (loopnum - 1) + max(score)
        ans2 = loopsum * loopnum
        if loopnum_mod != 0:
            ans2 = ans2 +max(0,max(score[:loopnum_mod]))
        ans =max(ans1,ans2)
    lastans = max(lastans,ans)

print(lastans)

Solution (Python):
'''
参考
https://marco-note.net/abc-175-work-log/
'''
N, K = map(int, input().split())        
P = list(map(int, input().split()))     
C = list(map(int, input().split()))     

ans = -float('inf')             

for piece in range(N):          
    S = []                      
    mov = P[piece] - 1          
    S.append(C[mov])            

    while mov != piece:             
        mov = P[mov] - 1            
        S.append(S[-1] + C[mov])    
    
    if K <= len(S):             
        score = max(S[:K])      
    elif S[-1] <= 0:            
        score = max(S)          
    else:
        score_a = S[-1] * (K // len(S))     
        rem = K % len(S)
        if rem != 0:
            score_a += max(0, max(S[:rem]))
        score_b = S[-1] * (K // len(S) - 1) 
        score_b += max(S)
        score = max(score_a, score_b)
    
    ans = max(ans, score)

print(ans)

Solution (Python):
def getN():
    return int(input())
def getNM():
    return map(int, input().split())
def getList():
    return list(map(int, input().split()))
def getArray(intn):
    return [int(input()) for i in range(intn)]
def input():
    return sys.stdin.readline().rstrip()
def rand_N(ran1, ran2):
    return random.randint(ran1, ran2)
def rand_List(ran1, ran2, rantime):
    return [random.randint(ran1, ran2) for i in range(rantime)]
def rand_ints_nodup(ran1, ran2, rantime):
  ns = []
  while len(ns) < rantime:
    n = random.randint(ran1, ran2)
    if not n in ns:
      ns.append(n)
  return sorted(ns)

def rand_query(ran1, ran2, rantime):
  r_query = []
  while len(r_query) < rantime:
    n_q = rand_ints_nodup(ran1, ran2, 2)
    if not n_q in r_query:
      r_query.append(n_q)
  return sorted(r_query)

from collections import defaultdict, deque, Counter
from sys import exit
from decimal import *
from heapq import heappop, heappush
from math import sqrt
from fractions import gcd
import random
import string
import copy
from itertools import combinations, permutations, product
from operator import mul, itemgetter
from functools import reduce
from bisect import bisect_left, bisect_right

import sys
sys.setrecursionlimit(1000000000)
mod = 10 ** 9 + 7





class Roop:
    def __init__(self, array):
        self.n = len(array)
        self.array = array
        
        self.roops = []
        
        self.roop_dict = [-1] * self.n
        
        self.opt_dic = {}
        ignore = [-1] * self.n
        cnt = 0
        for i in range(self.n):
            if ignore[i] >= 0:
                continue
            opt = [i]
            
            self.opt_dic[i] = 0
            c = 1
            
            ignore[i] = 1
            
            to = array[i]
            
            while True:
                if ignore[to] >= 0:
                    
                    if self.roop_dict[to] >= 0:
                        break
                    
                    for j in range(self.opt_dic[to], len(opt)):
                        self.roop_dict[opt[j]] = cnt
                    self.roops.append(opt[self.opt_dic[to]:])
                    
                    cnt += 1
                    break
                opt.append(to)
                ignore[to] = 1
                self.opt_dic[to] = c
                c += 1
                to = array[to]

    
    def roop_n(self, x):
        return self.roop_dict[x]

    
    
    def inspect(self, x):
        if self.roop_n(x) == -1:
            return False
        return self.roops[self.roop_dict(x)]

    
    def roop_len(self, x):
        return len(self.roops[self.roop_n(x)])

    
    def move(self, x, k):
        if k == 1:
            return x + 1
        cnt = k
        to = x
        
        
        head = []
        
        tail = []
        
        time = -1
        res = 0
        while cnt > 0:
            to = self.array[to]
            cnt -= 1
            
            if time == -1 and self.roop_n(to) >= 0:
                r = self.roops[self.roop_n(to)]
                time = (cnt // len(r))
                cnt -= time * len(r)
            
            if time == -1:
                head.append(to)
            
            else:
                tail.append(to)
        
        
        
        
        
        
        
        return to

N, K = getNM()
P = [i - 1 for i in getList()]
C = getList()

roop = Roop(P)


ans = -float('inf')
for r in roop.roops:
    n = len(r)
    
    alta = []
    for i in range(n):
        alta.append(C[r[i]])
    
    one_roop = sum(alta)
    alta += alta
    imos = [0]
    for i in range(len(alta)):
        imos.append(imos[i] + alta[i])

    t = min(n, K)
    for i in range(n):
        for j in range(1, t + 1):
            if one_roop >= 0:
                opt = (imos[i + j] - imos[i]) + ((K - j) // n) * one_roop
            else:
                opt = imos[i + j] - imos[i]
            ans = max(ans, opt)

print(ans)

Solution (Python):




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 = []


	

	ans = -1e19
	cycleID = 0

	for n in range(N):

		v = n
		currentCycleItemCnt = 0
		currentCycleTotal = 0

		if cycleIDs[v] != -1:
			currentCycleItemCnt, currentCycleTotal = cycleInfs[ cycleIDs[v] ]
			
		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

		for k in range(min(K,currentCycleItemCnt)):
			
			
			procCnt = k+1
			currentCycleSumTmp += C[v]

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

			
			ans = max( ans, currentCycleSumTmp + cycleLoopCnt * currentCycleTotal )
			v = P[v]


	print(ans)

Solution (Python):
import sys
N, K = map(int, input().split())
P = list(map(int, input().split()))
C = list(map(int, input().split()))
for i in range(N):
    P[i] -= 1

ans = -1e18
for i in range(N):
    s = []
    total = 0
    x = i
    while True:
        x = P[x]
        total += C[x]
        s.append(C[x])
        if x == i:
            break
    l = len(s)
    t = 0
    for j in range(l):
        t += s[j]
        if j + 1 > K:
            break
        now = t
        if total > 0:
            e = (K-(j+1))//l
            now += total * e
        ans = max(ans, now)

print(ans)

Solution (Python):
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 = map(int, input().split())
p = [*map(int, input().split())]
c = [*map(int, input().split())]
for i in range(n):
    p[i] -= 1

if max(c) < 0:
    print(max(c))
    sys.exit()

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)

Solution (Python):
N, K = map(int, input().split())
P = list(map(int, input().split()))
C = list(map(int, input().split()))

route = {}
point = {}

for idx, p in enumerate(P):
    route[idx+1] = p
    point[p] = C[p-1]

all_max = -float('inf')
for origin_start in range(1, N+1):
    visit = set()
    visit.add(origin_start)
    now_point = 0
    max_point = -float('inf')
    start = origin_start
    for k in range(K):
        now_point += point[start]
        max_point = max(max_point, now_point)
        start = route[start]
        if start in visit:
            roup_count = k + 1
            roup_point = now_point
            if now_point > 0:
              if K // roup_count >= 0:
                now_point = (K // roup_count) * roup_point
                start = origin_start
                for _ in range(K % roup_count):
                    now_point += point[start]
                    max_point = max(max_point, now_point)
                    start = route[start]

              if K // roup_count - 1 >= 0:
                now_point = (K // roup_count - 1) * roup_point
                start = origin_start
                for _ in range(roup_count):
                    now_point += point[start]
                    max_point = max(max_point, now_point)
                    start = route[start]
            break
        visit.add(start)

    all_max = max(max_point, all_max)
print(all_max)

Solution (Python):
def main():
    from sys import setrecursionlimit, stdin, stderr
    from os import environ
    from collections import defaultdict, deque, Counter
    from math import ceil, floor
    from itertools import accumulate, combinations, combinations_with_replacement
    setrecursionlimit(10**6)
    dbg = (lambda *something: stderr.write("\033[92m{}\033[0m".format(str(something)+'\n'))) if 'TERM_PROGRAM' in environ else lambda *x: 0
    input = lambda: stdin.readline().rstrip()
    LMIIS = lambda: list(map(int,input().split()))
    II = lambda: int(input())
    P = 10**9+7
    INF = 10**18+10
    N,K = LMIIS()
    P = list(map(lambda x: int(x)-1,input().split()))
    C = LMIIS()
    score_sets = []
    used = [False]*N
    tmp = P[0]
    for i in range(N):
        if not used[i]:
            tmp = i
            score_set = []
            while not used[tmp]:
                used[tmp] = True
                tmp = P[tmp]
                score_set.append(C[tmp])
            score_sets.append(score_set)
        
    ans = -INF
    for score_set in score_sets:
        
        len_set = len(score_set)
        sum_score_set_real = sum(score_set)
        sum_score_set = max(0,sum_score_set_real)


        
        for i in range(len_set):
            cum_sum_1 = 0
            for j in range(i,min(len_set, i+K)):
                cum_sum_1 += score_set[j]
                num_move = j-i+1
                tmp_max = cum_sum_1 + (K - num_move) // len_set * sum_score_set
                ans = max(ans, tmp_max)

        for i in range(1,len_set-1):
            cum_sum_2 = sum_score_set_real
            for j in range(i,min(len_set-1-(K-i),len_set-1)):
                cum_sum_2 -= score_set[j]
            for j in range(max(i,len_set-1-(K-i)),len_set-1):
                cum_sum_2 -= score_set[j]
                num_move = len_set - (j-i+1)
                tmp_max = cum_sum_2 + (K - num_move) // len_set * sum_score_set
                ans = max(ans,tmp_max)






        
                
    print(ans)

    
main()

Solution (Python):
def main():
    from sys import setrecursionlimit, stdin, stderr
    from os import environ
    from collections import defaultdict, deque, Counter
    from math import ceil, floor
    from itertools import accumulate, combinations, combinations_with_replacement
    setrecursionlimit(10**6)
    dbg = (lambda *something: stderr.write("\033[92m{}\033[0m".format(str(something)+'\n'))) if 'TERM_PROGRAM' in environ else lambda *x: 0
    input = lambda: stdin.readline().rstrip()
    LMIIS = lambda: list(map(int,input().split()))
    II = lambda: int(input())
    P = 10**9+7
    INF = 10**18+10
    N,K = LMIIS()
    P = list(map(lambda x: int(x)-1,input().split()))
    C = LMIIS()
    score_sets = []
    used = [False]*N
    tmp = P[0]
    for i in range(N):
        if not used[i]:
            tmp = i
            score_set = []
            while not used[tmp]:
                used[tmp] = True
                tmp = P[tmp]
                score_set.append(C[tmp])
            score_sets.append(score_set)
        
    ans = -INF
    for score_set in score_sets:
        
        len_set = len(score_set)
        sum_score_set_real = sum(score_set)
        


        
        for i in range(len_set):
            cum_sum_1 = 0
            for j in range(i,min(len_set, i+K)):
                cum_sum_1 += score_set[j]
                num_move = j-i+1
                tmp_max = cum_sum_1
                if sum_score_set_real > 0:
                    tmp_max += (K - num_move) // len_set * sum_score_set_real

                ans = max(ans, tmp_max)

        for i in range(1,len_set-1):
            cum_sum_2 = sum_score_set_real
            for j in range(i,min(len_set-1-(K-i),len_set-1)):
                cum_sum_2 -= score_set[j]
            for j in range(max(i,len_set-1-(K-i)),len_set-1):
                cum_sum_2 -= score_set[j]
                num_move = len_set - (j-i+1)
                tmp_max = cum_sum_2
                if sum_score_set_real > 0:
                    tmp_max += (K - num_move) // len_set * sum_score_set_real
                ans = max(ans,tmp_max)






        
                
    print(ans)

    
main()

Solution (Python):
def main():
    from sys import setrecursionlimit, stdin, stderr
    from os import environ
    from collections import defaultdict, deque, Counter
    from math import ceil, floor
    from itertools import accumulate, combinations, combinations_with_replacement
    setrecursionlimit(10**6)
    dbg = (lambda *something: stderr.write("\033[92m{}\033[0m".format(str(something)+'\n'))) if 'TERM_PROGRAM' in environ else lambda *x: 0
    input = lambda: stdin.readline().rstrip()
    LMIIS = lambda: list(map(int,input().split()))
    II = lambda: int(input())
    P = 10**9+7
    INF = 10**18+10
    N,K = LMIIS()
    P = list(map(lambda x: int(x)-1,input().split()))
    C = LMIIS()
    score_sets = []
    used = [False]*N
    tmp = P[0]
    for i in range(N):
        if not used[i]:
            tmp = i
            score_set = []
            while not used[tmp]:
                used[tmp] = True
                tmp = P[tmp]
                score_set.append(C[tmp])
            score_sets.append(score_set)
        
    ans = -INF
    for score_set in score_sets:
        
        len_set = len(score_set)
        sum_score_set_real = sum(score_set)
        sum_score_set = max(0,sum_score_set_real)


        
        for i in range(len_set):
            cum_sum_1 = 0
            for j in range(i,min(len_set, i+K)):
                cum_sum_1 += score_set[j]
                num_move = j-i+1
                tmp_max = cum_sum_1 + (K - num_move) // len_set * sum_score_set
                ans = max(ans, tmp_max)

        for i in range(1,len_set-1):
            cum_sum_2 = sum_score_set_real
            for j in range(i,min(len_set-1-(K-i),len_set-1)):
                cum_sum_2 -= score_set[j]
            for j in range(max(i,len_set-1-(K-i)),len_set-1):
                cum_sum_2 -= score_set[j]
                num_move = len_set - (j-i+1)
                tmp_max = cum_sum_2 + (K - num_move) // len_set * sum_score_set
                ans = max(ans,tmp_max)






        
                
    print(ans)

    
main()

Solution (Python):
def main():
    from sys import setrecursionlimit, stdin, stderr
    from os import environ
    from collections import defaultdict, deque, Counter
    from math import ceil, floor
    from itertools import accumulate, combinations, combinations_with_replacement
    setrecursionlimit(10**6)
    dbg = (lambda *something: stderr.write("\033[92m{}\033[0m".format(str(something)+'\n'))) if 'TERM_PROGRAM' in environ else lambda *x: 0
    input = lambda: stdin.readline().rstrip()
    LMIIS = lambda: list(map(int,input().split()))
    II = lambda: int(input())
    P = 10**9+7
    INF = 10**18+10
    N,K = LMIIS()
    P = list(map(lambda x: int(x)-1,input().split()))
    C = LMIIS()
    score_sets = []
    used = [False]*N
    tmp = P[0]
    for i in range(N):
        if not used[i]:
            tmp = i
            score_set = []
            while not used[tmp]:
                used[tmp] = True
                tmp = P[tmp]
                score_set.append(C[tmp])
            score_sets.append(score_set)
        
    ans = -INF
    for score_set in score_sets:
        
        len_set = len(score_set)
        sum_score_set_real = sum(score_set)
        sum_score_set = max(0,sum_score_set_real)


        
        for i in range(len_set):
            cum_sum_1 = 0
            for j in range(i,min(len_set, i+K)):
                cum_sum_1 += score_set[j]
                num_move = j-i+1
                tmp_max = cum_sum_1 + (K - num_move) // len_set * sum_score_set
                ans = max(ans, tmp_max)

        for i in range(1,len_set-1):
            cum_sum_2 = sum_score_set_real
            for j in range(i,min(len_set-1-(K-i),len_set-1)):
                cum_sum_2 -= score_set[j]
            for j in range(min(max(i,len_set-1-(K-i)),len_set-1),len_set-1):
                cum_sum_2 -= score_set[j]
                num_move = len_set - (j-i+1)
                tmp_max = cum_sum_2 + (K - num_move) // len_set * sum_score_set
                ans = max(ans,tmp_max)






        
                
    print(ans)

    
main()

Solution (Python):





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


	
	
	cycleIDs = [ -1 for _ in range(N) ]
	cycleInfs = []


	

	ans = -1e10
	cycleID = 0

	for n in range(N):

		v = n
		currentCycleItemCnt = 0
		currentCycleTotal = 0

		if cycleIDs[v] != -1:
			currentCycleItemCnt, currentCycleTotal = cycleInfs[ cycleIDs[v] ]
			
		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:

			
			
			procCnt += 1
			currentCycleSumTmp += C[v]
			if K < procCnt:
				break

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

			
			tmp = currentCycleSumTmp + cycleLoopCnt * currentCycleTotal
			ans = max( ans, tmp )

			v = P[v]
			if v == n:
				
				break

	return ans
	



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

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