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):
N, K = map(int,input().split())
P = [int(x)-1 for x in input().split()]
C = [int(x) for x in input().split()]

def loop(s):
    value = 0
    done = set()
    while s not in done:
        done.add(s)
        s = P[s]
        value += C[s]
    return len(done), value

def f(s,K):
    ans = -10**18
    total = 0
    done = set()
    while s not in done:
        done.add(s)
        s = P[s]
        total += C[s]
        ans = max(ans,total)
        K -= 1

        if K==0:
            return ans

    lamb, value = loop(s)

    if K > 2*lamb:
        if value > 0:
            K -= lamb
            total += (K//lamb)*value
            ans = max(ans,total)
            K -= (K//lamb)*lamb
            K += lamb
    if value <= 0:
        K = min(K,lamb+5)
        


    while K > 0:
        s = P[s]
        total += C[s]
        ans = max(ans,total)
        K -= 1
    return ans

print(max([f(s,K) for s in range(N)]))

Solution (Python):
import queue

N, K = map(int, input().split())
P = list(map(lambda v: v-1, map(int, input().split())))
C = list(map(int, input().split()))

visited = [False] * N
q = queue.Queue()
lists = list()

for i in range(N):
    q.put(dict(index=i, l=None))
    while not q.empty():
        d = q.get()
        if visited[d['index']]:
            continue
        visited[d['index']] = True
        l = d['l']
        if l is None:
            l = list()
            lists.append(l)
        l.append(C[d['index']])
        q.put(dict(index=P[d['index']], l=l))

maxv = -float('inf')

for l in lists:
    summ = sum(l)
    if summ > 0:
        score = summ * (K//len(l))
        rest = K % len(l)
        if rest == 0:
            score -= summ
            rest = len(l)
        for i in range(len(l)):
            v = 0
            for j in range(rest):
                v += l[i+j if i+j < len(l) else i+j-len(l)]
                maxv = max(maxv, score+v)
    else:
        for i in range(len(l)):
            v = 0
            for j in range(len(l)):
                v += l[i+j if i+j < len(l) else i+j-len(l)]
                maxv = max(maxv, v)
print(maxv)

Solution (Python):
n, k = map(int, input().split())
P = [int(x)-1 for x in input().split()]
C = [int(x) for x in input().split()]

vis = [0 for i in range(n+1)]
	

res = -10000000000000000000000
for i in range(0,n):
	if vis[i] == 0:
		su = 0
		vis[i] = 1
		v = []
		v.append(C[i])
		su += C[i]
		x = P[i]
		while x != i:
			vis[x] = 1
			su += C[x]
			v.append(C[x])
			x = P[x]
		vs = len(v)
		for ii in range(vs):
			umm = 0
			for j in range(vs):
				x = (ii+j)%vs
				umm += v[x]
				steps = 1+(x-ii+vs)%vs
				if k >= vs:
					if(su > 0):
						r = max((k-steps)//vs,0)
						res = max(res, r*su + umm)
					else:
						res = max(res,umm)
				else:
					if steps <= k:
						res = max(res,umm)


print(res)

Solution (Python):
n, k = map(int, input().split())
P = [int(x)-1 for x in input().split()]
C = [int(x) for x in input().split()]

vis = [0 for i in range(n+1)]
	

res = -10000000000000000000000
for i in range(0,n):
	if vis[i] == 0:
		su = 0
		vis[i] = 1
		v = []
		v.append(C[i])
		su += C[i]
		x = P[i]
		while x != i:
			vis[x] = 1
			su += C[x]
			v.append(C[x])
			x = P[x]
		vs = len(v)
		for ii in range(vs):
			umm = 0
			for j in range(min(k,vs)):
				x = (ii+j)%vs
				umm += v[x]
				steps = 1+(x-ii+vs)%vs
				if k >= vs:
					if(su > 0):
						r = max((k-steps)//vs,0)
						res = max(res, r*su + umm)
					else:
						res = max(res,umm)
				else:
					if steps <= k:
						res = max(res,umm)


print(res)

Solution (Python):
class Unionfind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    def root (self, x):
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.root(self.parents[x])
            return self.parents[x]

    def connect(self, x, y):
        x = self.root(x)
        y = self.root(y)
        if x == y:
            return
        if self.parents[x] > self.parents[y]:
            x, y = y, x
        self.parents[x] += self.parents[y]
        self.parents[y] = x

    def isConnect(self, x):
        return self.root(x) == self.root(y)

    def size(self, x):
        return -self.parents[self.root(x)]

N, K = map(int, input().split())
P = list(map(lambda x: int(x) - 1, input().split()))
C = list(map(int, input().split()))

INF = 10 ** 18
ans = -INF
dp = [[-INF] * (N + 1) for _ in range(N)]
uf = Unionfind(N)

for i in range(N):
    dp[i][0] = 0
    now = i
    for j in range(min(N, K)):
        now = P[now]
        dp[i][j + 1] = dp[i][j] + C[now]
        uf.connect(i, now)
        ans = max(ans, dp[i][j + 1])

for i in range(N):
    M = uf.size(i)
    if dp[i][M] <= 0:
        continue
    roop = K // M
    move = K % M
    if move == 0:
        roop -= 1
        move = M
    for j in range(move):
        ans = max(ans, dp[i][M] * roop + dp[i][j + 1])

print(ans)

Solution (Python):
n, k = list(map(int,input().split()))
jump = list(map(int,input().split()))
arr = list(map(int,input().split()))
best = - (10**28)
VV = []
 
for i in range(n):
  if i not in VV:
    order = []
    prev_pos = i
    visited = []
    sub_best = 0
    order = []
    l = 0
 
    for jjj in range(n):
      order.append(arr[prev_pos])
      
      visited.append(prev_pos)
      VV.append(prev_pos)
      l += 1
 
      next_pos = jump[prev_pos] - 1
      prev_pos = next_pos
      if next_pos in visited:
        break
 
    if sum(order)<1:
      limit = min(k,l*2)
      ss = 0
    else:
      limit = (k % l) + l
      limit = min(k,limit)
      ss = sum(order) * ((k//l) - 1)
      ss = max(ss,0) 
 
    sub_best = ss
   
    
    order = order + order + order
    
    for chuj in range(1,limit+1):
      kk = sum(order[0:0+chuj])
      best = max(best, sub_best + kk)
      for op in range(len(order)-chuj):
        kk -= order[op]
        kk += order[op+chuj]
        best = max(best, sub_best + kk)
      
print(best)

Solution (Python):
import sys
sys.setrecursionlimit(10**7)
def input(): return sys.stdin.readline().rstrip()


def main():
    n, k = map(int, input().split())
    p = tuple(map(int, input().split()))
    c = tuple(map(int, input().split()))
    ans = -10**18
    for i in range(n):
        start, count = i, 1
        val = c[start]
        while p[start]-1 != i:
            start = p[start]-1
            count += 1
            val += c[start]
        start = i
        if val > 0:
            a = (k//count-1)*val
            ans = max(a, ans)
            num = count + k % count
        else:
            a = 0
            num = min(k, count)
        for _ in range(num):
            a += c[start]
            start = p[start] - 1
            ans = max(a, ans)
    print(ans)


if __name__ == '__main__':
    main()

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

ans = -float('inf')
for i in range(n):
    s = []
    j = p[i]-1 
    s.append(c[j])
    while j != i:
        j = p[j]-1
        s.append(s[-1]+c[j])
    l = len(s)
    if k <= l:
        a = max(s[:k])
    elif s[-1] <= 0:
        a = max(s)
    else:
        w, r = divmod(k, l)
        a1 = s[-1]*(w-1) + max(s)
        a2 = s[-1]*w
        if r != 0:
            a2 += max(0, max(s[:r]))
        a = max(a1, a2)
    ans = max(ans, a)
print(ans)

Solution (Python):
N,K = map(int, input().split())
p = list(map(int, input().split()))
c = list(map(int, input().split()))

ans = -1*10**9
for si in range(N):
  x = si
  total = 0
  l = 0
  s = list()
  while(1):
    x = p[x]-1
    s.append(c[x])
    l += 1
    total += c[x]
    if x == si:
      break
  t = 0
  for i in range(l):
    now = 0
    if (i+1) > K:
      break
    t += s[i]
    now += t
    if total > 0:
      e = (K-(i+1)) // l
      now += total * e
    ans = max(ans, now)
print(ans)

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

P = list(map(int, input().split()))
C = list(map(int, input().split()))

for i in range(len(P)):
    P[i] -= 1

ans = float("-inf")
for i in range(N):
    cycle = []
    pos = i
    total = 0
    while True:
        pos = P[pos]
        cycle.append(C[pos])
        total += C[pos]
        if pos == i: break

    l = len(cycle)
    t = 0
    for j in range(l):
        t += cycle[j]
        if j + 1 > K: break
        now = t

        if total > 0:
            cnt = (K-j-1) // l
            now += total * cnt
        ans = max(ans, now)
print(ans)

Solution (Python):
from numba import njit
from sys import maxsize


@njit
def solve(n, k, p, c):
    used = [0] * n
    ss = []
    for i in range(n):
        if used[i]:
            continue
        now = i
        s = []
        while not used[now]:
            used[now] = 1
            s.append(c[now])
            now = p[now]
        ss.append(s)

    res = -maxsize
    for s in ss:
        s_len = len(s)
        cumsum = [0]
        
        for i in range(2*s_len):
            cumsum.append(cumsum[-1] + s[i%s_len])

        max_sum = [-maxsize] * s_len
        for i in range(s_len):
            for j in range(s_len):
                max_sum[j] = max(max_sum[j], cumsum[i+j] - cumsum[i])

        for i in range(s_len):
            if i > k:
                continue
            v = (k - i) // s_len
            if i == 0 and v == 0:
                continue
            if cumsum[s_len] > 0:
                res = max(res, max_sum[i] + cumsum[s_len] * v)
            elif i > 0:
                res = max(res, max_sum[i])
    print(res)


if __name__ == '__main__':
    n, k = map(int, input().split())
    p = list(map(lambda x: int(x)-1, input().split()))
    c = list(map(int, input().split()))
    solve(n, k, p, c)

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

if K<=N:
  ans = -10**9
  for i in range(N):
    now,last = i,0
    for _ in range(K):
      last += C[P[now]]
      ans = max(ans,last)
      now=P[now]
  print(ans)
  exit()
ans = -10**9
for i in range(N):
  tmp,now,done = [0],i,set()
  for _ in range(N+1):
  
    tmp.append(tmp[-1]+C[P[now]])
    if P[now] == i:
      break
    now = P[now]
  tmp = tmp[1:]
  cnt = len(tmp)
  m = max(tmp)
  ans = max(ans,m,tmp[-1]*(K//cnt-1)+m)
  if K%cnt != 0:
    ans = max(ans, tmp[-1]*(K//cnt)+max(tmp[:K%cnt]))
    
print(ans)

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


C_max = max(C[1:])
if C_max < 0:
    print(C_max)
    exit()


ans = 0

done = [False] * (N + 1) 




for i in range(1, N + 1):
    if done[i]:
        continue
        

    loop = [i] 
    now = P[i] 
    while now != i:
        loop.append(now)
        done[now] = True
        now = P[now]
        

    
    

    L = len(loop)
    S = sum(C[v] for v in loop) 

    for a_ind in range(L):
        a = loop[a_ind]
        score_ab = -C[a]
        
        for b_ind in range(a_ind, a_ind + L):
            dist_ab = b_ind - a_ind
            if dist_ab > K:
                break
            b = loop[b_ind % L]
            score_ab += C[b]

            max_score = score_ab + max(0, S) * ((K - dist_ab) // L)
            
            
            
            

            ans = max(ans, max_score)

print(ans)

Solution (Python):

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



used = [0] * N
ss = []
for i in range(N):
    if used[i]: continue
    cur = i
    s = []
    while used[cur] == 0:
        used[cur] = 1
        s.append(C[cur])
        cur = P[cur] - 1 
    ss.append(s)


res = -float("inf")
for vec in ss:
    M = len(vec)
    
    
    accum = [0] * (2*M+1)
    for i in range(M*2):
        accum[i+1] = accum[i] + vec[i%M]

    
    amari = [-float("inf")] * M
    for i in range(M):
        for j in range(M):
            amari[j] = max(amari[j], accum[i+j]-accum[i])

    
    for r in range(M):
        if r > K: continue
        q = (K - r) // M 
        if r == 0 and q == 0: continue

        if accum[M] > 0:
            res = max(res, amari[r] + accum[M] * q)
        elif r > 0:
            res = max(res, amari[r])

print(res)

Solution (Python):
from numba import jit
@jit
def main():
  n,k=map(int,input().split(" "))
  p=list(map(int,input().split(" ")))
  c=list(map(int,input().split(" ")))
  ans=-10**18
  for i in range(n):
    start,count=i,1
    val=c[start]
    while p[start]-1!=i: 
      start=p[start]-1
      count+=1
      val+=c[start]
    start=i
    
    '''
    以下の基本的な方針は
    - 1ループ分のスコア合計が正であればできるだけループしてスコアを稼ぎ、残りの余りの分の最大をとる。
    - 1ループ分のスコア合計が負であればループ回数を0にして、1ループ以内で最大となる移動を求める。
    しかし、ループ回数が最大であればいいとは限らない。
    x回ループできたとしてcount%k回の余りの分を調べても、x-1回ループし次の1回のループのなかで1周仕切らない移動が最大になる可能性がある。
    なのでx-1回分のループだけ取り切ってしまい、残りcount+k%count(＝「1周半」)の中で最大を調べる必要がある。
    また、負の場合は基本的に1周以内だが、kが極端に小さいときの処理が必要。
    '''
    if val>0:
      a=(k//count-1)*val  
      ans=max(a,ans)
      num=count+k%count
    else:
      a=0
      num=min(k,count)  
    for _ in range(num):
      start=p[start]-1
      a+=c[start]
      ans=max(a,ans)
  print(ans)
main()

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

maxscore = -(10 ** 18)

for st in range(N):
	cumsum = [0]
	now = st
	while(P[now] != st):
		now = P[now]
		cumsum.append(cumsum[-1] + C[now])
	cumsum.append(cumsum[-1] + C[st])
	
	m = len(cumsum) - 1
	loopsum = cumsum[-1]
	
	if loopsum < 0:
		maxscore = max(maxscore, max(cumsum[1:min(K + 1, m + 1)]))
		continue
	
	score = (K // m - 1) * loopsum
	extended_cumsum = cumsum + [cumsum[i] + loopsum for i in range(1, K % m + 1)]
	score += max(extended_cumsum)
	maxscore = max(maxscore, score)
print(maxscore)

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

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

for i in range(len(p)):
    p[i] -= 1

ans = float("-inf")

for i in range(N):
    
    pos = i
    
    point = []
    total = 0
    while True:
        pos = p[pos]
        point.append(c[pos])
        
        total += c[pos]
        
        if pos == i: break
    l = len(point)

    t = 0
    
    for i in range(l):
        t += point[i]
        
        if i+1 > K: break
        now = t
        if total > 0:
            
            
            
            cnt = (K-i-1) // l
            now += total * cnt 
        ans = max(ans, now)
print(ans)

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

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

for i in range(len(p)):
    p[i] -= 1

ans = float("-inf")

for i in range(N):
    
    pos = i
    
    point = []
    total = 0
    while True:
        pos = p[pos]
        point.append(c[pos])
        
        total += c[pos]
        
        if pos == i: break
    l = len(point)

    t = 0
    
    for i in range(l):
        t += point[i]
        
        if i+1 > K: break
        now = t
        if total > 0:
            
            
            cnt = (K-i-1) // l
            now += total * cnt 
        ans = max(ans, now)
print(ans)

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

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

for i in range(len(p)):
    p[i] -= 1

ans = float("-inf")

for i in range(N):
    
    pos = i
    
    point = []
    total = 0
    while True:
        pos = p[pos]
        point.append(c[pos])
        
        total += c[pos]
        
        if pos == i: break
    l = len(point)

    t = 0
    
    for i in range(l):
        t += point[i]
        
        if i+1 > K: break
        now = t
        if total > 0:
            
            
            now += (total * ((K-i-1)//l))
        ans = max(ans, now)
print(ans)

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

ans = -float('inf')
for i in range(n):
    s = []
    j = p[i]-1 
    s.append(c[j])
    while j != i:
        j = p[j]-1
        s.append(s[-1]+c[j])
    l = len(s)
    if k <= l:
        a = max(s[:k])
    elif s[-1] <= 0:
        a = max(s)
    else:
        w, r = divmod(k, l)
        a1 = s[-1]*(w-1) + max(s)
        a2 = s[-1]*w
        if r != 0:
            a2 += max(0, max(s[:r]))
        a = max(a1, a2)
    ans = max(ans, a)
print(ans)

'''

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

ans = -float('inf')
for i in range(n):
    j = p[i] - 1
    s = [c[j]]
    while j != i:
        j = p[j] - 1
        s.append(s[-1] + c[j])
    l = len(s)
    if k <= l:
        score = max(s[:k])
    elif s[-1] <= 0:
        score = max(s)
    else:
        w, r = divmod(k, l)
        score1 = s[-1] * (w - 1)
        score1 += max(s)
        score2 = s[-1] * w
        if r != 0:
            score2 += max(0, max(s[:r]))
        score = max(score1, score2)

    ans = max(ans, score)

print(ans)
'''

Solution (Python):
import math
import sys
import os

sys.setrecursionlimit(10**7)

def _S(): return sys.stdin.readline().rstrip()
def I(): return int(_S())
def LS(): return list(_S().split())
def LI(): return list(map(int,LS()))

if os.getenv("LOCAL"):
    inputFile = basename_without_ext = os.path.splitext(os.path.basename(__file__))[0]+'.txt'
    sys.stdin = open(inputFile, "r")
INF = float("inf")

N,K = LI()
P = LI()
C = LI()

P = list(map(lambda x:x-1,P))

res = -INF
used = [False] * N
ss = []

for i in range(N):
    
    if used[i]:
        continue
    cur = i
    s = []
    while not used[cur]:
        used[cur] = True
        s.append(C[cur])
        cur = P[cur]
        
    ss.append(s)



for vec in ss:
    M = len(vec)
    
    sum = [0]*(2*M + 1)
    for i in range(2*M):
        sum[i+1] = sum[i]+vec[i%M]
    
    
    amari = [-INF]*M
    for i in range(M):
        for j in range(M):
            amari[j] = max(amari[j],sum[i+j] - sum[i])
    
    for r in range(M):
        if r>K:
            continue
        q = (K-r)//M
        if r==0 and q==0:
            continue
        if sum[M]>0:
            res = max(res, amari[r] + sum[M] * q)
        elif r > 0:
            res = max(res, amari[r])
print(res)

Solution (Python):

"""
1周未満で終わる時の最大値をまずもとめる
(i)k<一周なら
最大値を出力して終了
(ii)sum(lst) <= 0
1周以上する価値はないので、最大値を出力して終了
(iii)sum(lst) > 0
N%kの端数だけ愚直にもう一度最大値を求めて出力
"""
import sys
readline = sys.stdin.buffer.readline
def even(n): return 1 if n%2==0 else 0

n,k = map(int,readline().split())
p = list(map(int,readline().split()))
c = list(map(int,readline().split()))
p = [i-1 for i in p]

ans = -10**18

for i in range(n):
    lst1 = [c[i]]
    idx = p[i]
    while idx != i:
        lst1.append(c[idx])
        idx = p[idx]
    sm = sum(lst1)
    acc = 0
    for i in range(min(len(lst1),k+2)):
        acc += lst1[i]
        a = acc
        if sm > 0:
            a += sm*((k-(i+1))//len(lst1))
        ans = max(a,ans)
print(ans)

Solution (Python):

import sys
from itertools import chain


def max_add_1_to_n(loop, n):
    
    l = len(loop)
    acc = loop.copy()
    
    max_val = max(acc)
    for i in range(1, n):
        for j in range(0, l):
            acc[j] += loop[(i + j) % l]
        
        max_val = max(max(acc), max_val)
    return max_val


def max_add_0_to_n(loop, n):
    
    if n >= 1:
        return max(max_add_1_to_n(loop, n), 0)
    else:
        return 0


def max_loop_k(loop, K):
    l = len(loop)
    if K <= 2 * l:
        return max_add_1_to_n(loop, K)
    
    l_sum = sum(loop)
    if l_sum <= 0:
        return max_add_1_to_n(loop, l)
    else:
        Kdiv = K // l
        Kmod = K % l
        
        return max_add_0_to_n(loop, l + Kmod) + l_sum * (Kdiv - 1)


def solve(N: int, K: int, P: "List[int]", C: "List[int]"):
    
    
    P = [i - 1 for i in P]
    answer = -float("inf")
    for i0 in range(N):
        if P[i0] == -1:
            continue
        loop = []
        i = i0
        while P[i] != -1:
            loop.append(C[i])
            i_next = P[i]
            P[i] = -1
            i = i_next
        answer = max(answer, max_loop_k(loop, K))

    return answer


def main():
    tokens = chain(*(line.split() for line in sys.stdin))
    N = int(next(tokens))  
    K = int(next(tokens))  
    P = [int(next(tokens)) for _ in range(N)]  
    C = [int(next(tokens)) for _ in range(N)]  
    answer = solve(N, K, P, C)
    print(answer)


if __name__ == "__main__":
    main()

Solution (Python):
from numba import jit
@jit
def main():
  n,k=map(int,input().split())
  p=list(map(int,input().split()))
  c=list(map(int,input().split()))
  ans=-10**18
  for i in range(n):
    start,count=i,1
    val=c[start]
    while p[start]-1!=i: 
      start=p[start]-1
      count+=1
      val+=c[start]
    start=i
    if val>0:
      a=(k//count-1)*val 
      ans=max(a,ans)
      num=count+k%count
    else:
      a=0
      num=min(k,count)
    for _ in range(num):
      start=p[start]-1
      a+=c[start]
      ans=max(a,ans)
  print(ans)
main()

Solution (Python):
N, K = map(int, input().split())
moves = [0] + list(map(int, input().split()))
points = [0] + list(map(int, input().split()))
INF = 10**10

arrived = [0 for _ in range(N+1)]
answer = -INF
for move in range(1, N+1):
  if arrived[move] == 1:
    continue
  else:
    arrived[move] = 1
    komas = [move]
    next = moves[move]
    while(arrived[next] == 0):
      arrived[next] = 1
      komas.append(next)
      next = moves[next]
    len_k = len(komas)
    sum_k = [0 for _ in range(len_k*2)]
    sum_k[0] = points[komas[0]]
    for i in range(1, len_k*2):
      sum_k[i] = sum_k[i-1] + points[komas[i%len_k]]
    scores = [-INF for _ in range(len_k+1)]
    for j in range(len_k):
      for k in range(1, len_k+1):
        scores[k] = max(scores[k], sum_k[j+k] - sum_k[j])
    if K > len_k and scores[len_k] > 0:
      max_s = -INF
      max_k = -INF
      for m in range(1, len_k+1):
        if m <= K%len_k:
          max_k = max(max_k, scores[m])
        max_s = max(max_s, scores[m])
      answer = max(answer, max_k+scores[len_k]*(K//len_k), max_s+scores[len_k]*(K//len_k-1))
    else:
      max_s = -INF
      for m in range(1, min(K, len_k)+1):
        max_s = max(max_s, scores[m])
      answer = max(answer, max_s)
print(answer)

Solution (Python):
import bisect, collections, copy, heapq, itertools, math, string, sys
input = lambda: sys.stdin.readline().rstrip() 
sys.setrecursionlimit(10**7)
INF = float('inf')
def I(): return int(input())
def F(): return float(input())
def SS(): return input()
def LI(): return [int(x) for x in input().split()]
def LI_(): return [int(x)-1 for x in input().split()]
def LF(): return [float(x) for x in input().split()]
def LSS(): return input().split()

def resolve():
    N, K = LI()
    P = LI_()
    C = LI()

    ans = -INF
    for i in range(N):
        
        cycle = []
        c = i
        while True:
            c = P[c]
            cycle.append(c)
            if c == i:
                break
        len_cycle = len(cycle)
        

        
        score = 0
        cycle_score_total = sum([C[j] for j in cycle])
        cycle_score_cum = list(itertools.accumulate([C[j] for j in cycle]))
        
        for j in range(min(len_cycle, K)):
            score = cycle_score_cum[j]
            if cycle_score_total > 0:
                score += (K - j - 1) // len_cycle * cycle_score_total
            
            ans = max(score, ans)

    print(ans)

if __name__ == '__main__':
    resolve()

Solution (Python):
"""
1. マス同士は有効グラフの一本道になっている。で、必ずどこかでループが発生している。

2. 各点から各点に移動する場合のスコアの合計とステップ数(ループ内の場合は一周以内のもの)を前処理(dfs)で求めておく。dp[i][j] => iからjまでのスコアとステップ数

3. K > N の場合、ループを通るとスコアがマイナスになるなら（dp[i][i]がマイナスになるようなiが存在するなら）、ループを一周しない方がよい。
ループを通るとスコアがプラスになるなら、

各iに対して地点iからスタートする場合というのをシミュレートすると実装が楽そう。
K <= Nの場合はi番目からスタートして、dfsでstep数がKに到達するまで進み続けて、スコアの最大値を図る。
Kが大きい場合は、dfsで道をたどっていってループを検出したら、その時点でループスコアがマイナスかプラスかを判断して、マイナスなら終了。
プラスならループスコア*(K//ループstep)を加算してできる限りKを減らす。そこからstep数がKに到達するまでdfsで道をたどっていって最大値を求める。
各スタート地点ごとにO(N)で処理可能なので、全体ではO(N^2)で処理できる
"""
N,K = map(int,input().split())
P = list(map(int,input().split()))
C = list(map(int,input().split()))

ans = -float("INF")

for i in range(1,N+1):
    scores = [None]*(N+1)
    steps = [None]*(N+1)
    cur = i
    score = 0
    step = 0
    loopFlag = False
    while step <= K:
        if scores[cur]!=None and not loopFlag:
            loopFlag = True
            loopScore = score - scores[cur]
            loopStep = step - steps[cur]
            ans = max(ans,score)
            restLoop = (K-step)//loopStep
            if restLoop > 0:
                restLoop -= 1
            score += restLoop*loopScore
            step += restLoop*loopStep
        scores[cur] = score
        steps[cur] = step
        if step != 0:
            ans = max(ans,score)
        p = P[cur-1]
        c = C[p-1]
        cur = p
        score += c
        step += 1

print(ans)

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

ans = -1_000_000_000
for i in range(N):
    S = [C[i]]
    p = P[i]
    while p != i:
        S.append(C[p])
        p = P[p]
    s = sum(S)
    n = len(S)
    acc = 0
    for i in range(min(n, K + 2)):
        acc += S[i]
        a = acc
        if s > 0:
            a += s * ((K - (i + 1)) // n)
        ans = max(a, ans)

print(ans)

Solution (Python):















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 = int(-1e14)
for i in range(n):
    tmp = []
    cycle = 0
    index = i
    while True:
        index = p[index]
        tmp.append(c[index])
        cycle += c[index]
        if i == index:
            break
    
    l = len(tmp)
    t = 0
    for j in range(l):
        t += tmp[j]
        if j >= k:
            break
        cur = t
        if cycle > 0:
            e = int((k-j-1) / l)
            cur += e * cycle
        ans = max(cur, ans)
        
print(ans)

Solution (Python):
import numpy as np
import numba
from numba import njit, b1, i4, i8, f8

@njit((i8,i8,i8[:],i8[:]), cache=True)
def main(N,K,P,C):
  INF = 1<<30
  ans = -INF
  for i in range(N):
    score = 0
    now = i
    visited = np.full(N,-1,np.int64)
    scores = np.zeros(N,np.int64)
    visited[now] = 0
    for j in range(1,K+1):
      now = P[now]
      score += C[now]
      ans = max(ans, score)
      if visited[now]>=0:
        cyc = j - visited[now]
        up = score - scores[now]
        break
      scores[now] = score
      visited[now] = j
    else:
      continue
    if up<=0:
      continue
    cnt = j+1
    if K-cyc>=j:
      score += (K-cyc-j)//cyc * up
      ans = max(ans, score)
      cnt += (K-cyc-j)//cyc*cyc
    for j in range(cnt,K+1):
      now = P[now]
      score += C[now]
      ans = max(ans, score)
  return ans

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

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

Solution (Python):
n, k = map(int, input().split())
p_list = list(map(lambda x: int(x) - 1, input().split()))
c_list = list(map(int, input().split()))

max_score = -(1 << 64)
cycles = []
cycled = [False] * n
for i in range(n):
    if cycled[i]:
        continue

    cycle = [i]
    cycled[i] = True
    while p_list[cycle[-1]] != cycle[0]:
        cycle.append(p_list[cycle[-1]])
        cycled[cycle[-1]] = True

    cycles.append(cycle)

for cycle in cycles:
    cycle_len = len(cycle)

    accum = [0]
    for i in range(cycle_len * 2):
        accum.append(accum[-1] + c_list[cycle[i % cycle_len]])

    cycle_score = accum[cycle_len]

    max_series_sums = [max([accum[i + length] - accum[i]
                            for i in range(cycle_len)])
                       for length in range(cycle_len + 1)]

    if cycle_len >= k:
        score = max(max_series_sums[1:k + 1])
    elif cycle_score <= 0:
        score = max(max_series_sums[1:])
    else:
        max_cycle_num, cycle_rem = divmod(k, cycle_len)
        score = max(cycle_score * (max_cycle_num - 1) + max(max_series_sums),
                    cycle_score * max_cycle_num + max(max_series_sums[:cycle_rem + 1]))

    max_score = max(max_score, score)

print(max_score)