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):
def solve():
    from collections import defaultdict
    class UnionFind():
        def __init__(self, n):
            self.n = n
            self.par = [-1] * n

        def find(self, x):
            if self.par[x] < 0:
                return x
            else:
                while self.par[x] >= 0:
                  x = self.par[x]
                return x

        def unite(self, x, y):
            x = self.find(x)
            y = self.find(y)

            if x == y:
                return

            if self.par[x] > self.par[y]:
                x, y = y, x

            self.par[x] += self.par[y]
            self.par[y] = x

        def size(self, x):
            return -self.par[self.find(x)]

        def same(self, x, y):
            return self.find(x) == self.find(y)

    n, k = map(int, input().split())
    p = list(map(int, input().split()))
    c = list(map(int, input().split()))
    mp = defaultdict(int)
    uf = UnionFind(n)

    for i in range(n):
        uf.unite(i, p[i] - 1)

    for i in range(n):
        mp[uf.find(i)] += c[i]

    ans = -10 ** 14
    for i in range(n):
        roop = uf.size(i)
        times = (k - 1) // roop if mp[uf.find(i)] > 0 else 0
        over = max(min(roop, k - roop * times), 1)
        tmp = 0
        s = -10 ** 10
        idx = i
        for j in range(over):
            tmp += c[idx]
            s = max(s, tmp)
            idx = p[idx] - 1
        s += times * mp[uf.find(i)]
        ans = max(ans, s)
    print(ans)


solve()

Solution (Python):
import sys
input = sys.stdin.readline

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):
    now = i
    visit = [False]*N
    visit[now] = True
    l = []
    
    for _ in range(N+10):
        nex = P[now]-1
        l.append(C[nex])
        
        if visit[nex]:
            break
        
        visit[nex] = True
        now = nex
    
    s = sum(l)
    now = 0
    
    for i in range(min(K, len(l))):
        now += l[i]
        ans = max(ans, now+(K-i-1)//len(l)*max(0, s))
    
print(ans)

Solution (Python):
import bisect
import collections
import copy
import functools
import heapq
import math
import sys
from collections import deque
from collections import defaultdict
input = sys.stdin.readline
sys.setrecursionlimit(10**9)
MOD = 10**9+7

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

sumlist1 = [[0]*N for _ in range(N)]
walist = [[0]*N for _ in range(N)]
loopcount = [0]*N

for h in range(N):
    sumlist1[h][0] = C[h]
    walist[h][0] = C[h]
    now = h
    l = 0
    for i in range(1,N):
        now = P[now]-1

        if sumlist1[h][i-1] < 0:
            sumlist1[h][i] = C[now]
        else:
            sumlist1[h][i] += sumlist1[h][i-1] + C[now]
        walist[h][i] += walist[h][i-1] + C[now]
        
        l += 1
        if now == h:
            break
    else:
        l += 1
    loopcount[h] = l


maxlist = [0]*N
for i in range(N):
    T = loopcount[i]
    wa = walist[i][T-1]
    

    loop = K//T
    amari = K%T

    if wa >= 0:
        if loop == 0:
            if amari != 0:
                maxlist[i] = wa*loop + max(sumlist1[i][:amari])
            else:
                maxlist[i] = max(sumlist1[i][:amari])
        else:
            if amari != 0:
                maxlist[i] = max(wa*loop + max(sumlist1[i][:amari]), wa*(loop-1) + max(sumlist1[i]))
            else:
                maxlist[i] = max(wa*loop, wa*(loop-1) + max(sumlist1[i][:T]))
            

    else:
        if loop == 0:
            maxlist[i] = max(sumlist1[i][:amari])
        else:
            maxlist[i] = max(sumlist1[i])

print(max(maxlist))

Solution (Python):
import sys
from collections import defaultdict

sys.setrecursionlimit(10 ** 7)
rl = sys.stdin.readline


class UnionFind:
    def __init__(self, n: int):
        self.n = n
        self.parents = [-1] * n
    
    def find(self, x: int):
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]
    
    def union(self, x: int, y: int):
        x = self.find(x)
        y = self.find(y)
        
        if x == y:
            return
        if self.parents[y] < self.parents[x]:
            x, y = y, x
        
        self.parents[x] += self.parents[y]
        self.parents[y] = x
    
    def size(self, x: int):
        return -self.parents[self.find(x)]
    
    def same(self, x: int, y: int):
        return self.find(x) == self.find(y)
    
    def members(self, x: int):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]
    
    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]
    
    def group_count(self):
        return len(self.roots())
    
    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}
    
    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())


def solve():
    N, K = map(int, rl().split())
    P = list(map(lambda n: int(n) - 1, rl().split()))
    C = list(map(int, rl().split()))
    
    uf = UnionFind(N)
    for i in range(N):
        uf.union(i, P[i])
    roop_scores = defaultdict(int)
    for i in range(N):
        roop_scores[uf.find(i)] += C[i]
    
    ans = -(10 ** 18)
    K -= 1
    for s in range(N):
        cur = P[s]
        tmp = C[cur]
        ans = max(ans, tmp)
        roop_size = uf.size(s)
        roop_score = roop_scores[uf.find(s)]
        roop_cnt = K // roop_size
        if roop_cnt and 0 < roop_score:
            tmp += roop_score * roop_cnt
            rem = K % roop_size
            ans = max(ans, tmp)
            while rem:
                cur = P[cur]
                tmp += C[cur]
                ans = max(ans, tmp)
                rem -= 1
            continue
        cnt = min(roop_size, K)
        while cnt:
            cur = P[cur]
            tmp += C[cur]
            ans = max(ans, tmp)
            cnt -= 1
    print(ans)


if __name__ == '__main__':
    solve()

Solution (Python):
f=lambda:[*map(int,input().split())]
n,k=f()
p,c=f(),f()
p=[i-1 for i in p]
a=-10**9
for i in range(n):
  x,l,s,t=i,[],0,0
  while 1:
    x=p[x]
    l+=[c[x]]
    s+=c[x]
    if x==i: break
  m=len(l)
  for j in range(m):
    if j+1>k: break
    t+=l[j]
    a=max(a,t+(k-j-1)//m*s*(s>0))
print(a)

Solution (Python):
f=lambda:[*map(int,input().split())]
n,k=f()
p,c=f(),f()
p=[*map(lambda x:x-1,p)]
a=-10**9
for i in range(n):
  x=i
  l=[]
  s=0
  while 1:
    x=p[x]
    l+=[c[x]]
    s+=c[x]
    if x==i: break
  m=len(l)
  t=0
  for j in range(m):
    if j+1>k: break
    t+=l[j]
    a=max(a,t+(k-j-1)//m*s*(s>0))
print(a)

Solution (Python):
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):
    x = i
    loop = []
    total = 0
    while True:
        x = P[x] - 1
        loop.append(C[x])
        total += C[x]
        if x == i:
            break

    T = len(loop)
    tmp = 0
    for j in range(T):
        tmp += loop[j]
        if K < j + 1:
            break
        now = tmp
        
        if total > 0:
            loop_times = (K - (j + 1)) // T
            now += total * loop_times

        ans = max(ans, now)
print(ans)

Solution (Python):
import sys

read = sys.stdin.read
readline = sys.stdin.readline
readlines = sys.stdin.readlines
sys.setrecursionlimit(10 ** 9)
INF = 1 << 60
MOD = 1000000007


def main():
    N, K = map(int, readline().split())
    P = [int(s) - 1 for s in readline().split()]
    C = list(map(int, readline().split()))

    ans = -INF
    for i in range(N):
        score = []
        total = 0
        x = i
        while True:
            x = P[x]
            score.append(C[x])
            total += C[x]
            if x == i:
                break

        l = len(score)
        csum = 0
        for i in range(l):
            if i + 1 > K:
                break
            csum += score[i]
            res = csum
            if total > 0:
                res += (K - (i + 1)) // l * total

            if ans < res:
                ans = res

    print(ans)
    return


if __name__ == '__main__':
    main()

Solution (Python):
N, K = map(int, input().split())
P = list(map(int, input().split()))
for i in range(N):
    P[i] -= 1
C = list(map(int, input().split()))
 
ans = -(10 ** 18)
 
for si in range(N):
    x = si
    loop = []
    total = 0
    while 1:
        x = P[x]
        loop.append(C[x])
        total += C[x]
        if x == si:
            break
    T = len(loop)  
    tmp = 0
    for i in range(T):
        tmp += loop[i]
        if K < i + 1:
            break
        now = tmp
        if total > 0:  
            loop_times = (K - (i + 1)) // T  
            now += total * loop_times
        ans = max(ans, now)
 
print(ans)

Solution (Python):
import sys, re
from collections import deque, defaultdict, Counter
from math import ceil, sqrt, hypot, factorial, pi, sin, cos, tan, asin, acos, atan, radians, degrees, log2, gcd
from itertools import accumulate, permutations, combinations, combinations_with_replacement, product, groupby
from operator import itemgetter, mul
from copy import deepcopy
from string import ascii_lowercase, ascii_uppercase, digits
from bisect import bisect, bisect_left, insort, insort_left
from heapq import heappush, heappop
from functools import reduce, lru_cache
def input(): return sys.stdin.readline().strip()
def INT(): return int(input())
def MAP(): return map(int, input().split())
def LIST(): return list(map(int, input().split()))
def TUPLE(): return tuple(map(int, input().split()))
def ZIP(n): return zip(*(MAP() for _ in range(n)))
sys.setrecursionlimit(10 ** 9)
INF = float('inf')
mod = 10 ** 9 + 7 

from decimal import *



N, K = MAP()
P = LIST()
C = LIST()

check = [0]*N 
score = []

i = 0
while 1:
	while i < N and check[i]:
		i += 1
	if i == N:
		break

	tmp = []
	while check[i] == 0:
		check[i] = 1
		i = P[i]-1
		tmp.append(C[i])
	score.append(tmp)

ans = -INF
for x in score:
	x_acc = list(accumulate([0] + x + x))
	n = len(x)
	tmp_max = -INF

	for i, j in combinations(range(2*n+1), 2):
		if j-i <= min(K, n):
			if tmp_max < x_acc[j]-x_acc[i]:
				tmp_max = x_acc[j]-x_acc[i]
				cnt = j-i
	tmp_ans = -INF

	if 0 >= x_acc[n]:
		tmp_ans = tmp_max

	else:
		if cnt <= K%n:
			tmp_ans = x_acc[n]*(K//n) + tmp_max
		else:
			tmp_max2 = 0
			for i, j in combinations(range(2*n+1), 2):
				if j-i <= K%n:
					if tmp_max2 < x_acc[j]-x_acc[i]:
						tmp_max2 = x_acc[j]-x_acc[i]
			tmp_ans = max(x_acc[n]*(K//n-1)+tmp_max, x_acc[n]*(K//n) + tmp_max2)

	ans = max(ans, tmp_ans)

print(ans)

Solution (Python):
from collections import defaultdict, deque, Counter
from heapq import heappush, heappop, heapify
import math
import bisect
import random
from itertools import permutations, accumulate, combinations, product
import sys
from pprint import pprint
from copy import deepcopy
import string
from bisect import bisect_left, bisect_right
from math import factorial, ceil, floor
from operator import mul
from functools import reduce
from pprint import pprint


sys.setrecursionlimit(2147483647)
INF = 10 ** 20
def LI(): return list(map(int, sys.stdin.readline().split()))
def I(): return int(sys.stdin.readline())
def LS(): return sys.stdin.buffer.readline().rstrip().decode('utf-8').split()
def S(): return sys.stdin.buffer.readline().rstrip().decode('utf-8')
def IR(n): return [I() for i in range(n)]
def LIR(n): return [LI() for i in range(n)]
def SR(n): return [S() for i in range(n)]
def LSR(n): return [LS() for i in range(n)]
def SRL(n): return [list(S()) for i in range(n)]
def MSRL(n): return [[int(j) for j in list(S())] for i in range(n)]
mod = 1000000007



class UnionFind:
    def __init__(self, n):
        
        
        self.table = [-1] * n
        self.size = [1] * n
        

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

    def get_size(self, x):
        r = self.root(x)
        return self.size[r]

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

    def union(self, x, y):
        r1 = self.root(x)
        r2 = self.root(y)
        if r1 == r2:
            return
        
        d1 = self.table[r1]
        d2 = self.table[r2]
        if d1 <= d2:
            self.table[r2] = r1
            self.size[r1] += self.size[r2]
            if d1 == d2:
                self.table[r1] -= 1
        else:
            self.table[r1] = r2
            self.size[r2] += self.size[r1]
        

n, k = LI()
P = LI()
C = LI()
U = UnionFind(n)
for i in range(n):
    U.union(P[i] - 1, i)

D = defaultdict(int)
for i in range(n):
    D[U.root(i)] += C[i]

ans = -INF
k -= 1
for j in range(n):
    now = P[j] - 1
    r = D[U.root(now)]
    m = U.get_size(now)
    ret = C[now]
    ans = max(ans, ret)
    if k // m and r >= 0:
        ret += k // m * r
        ans = max(ans, ret)
        for l in range(k % m):
            now = P[now] - 1
            ret += C[now]
            ans = max(ans, ret)
    ret = C[now]
    for l in range(min(m, k)):
        now = P[now] - 1
        ret += C[now]
        ans = max(ans, ret)

print(ans)

Solution (Python):
from collections import defaultdict, deque, Counter
from heapq import heappush, heappop, heapify
import math
import bisect
import random
from itertools import permutations, accumulate, combinations, product
import sys
from pprint import pprint
from copy import deepcopy
import string
from bisect import bisect_left, bisect_right
from math import factorial, ceil, floor
from operator import mul
from functools import reduce
from pprint import pprint


sys.setrecursionlimit(2147483647)
INF = 10 ** 20
def LI(): return list(map(int, sys.stdin.readline().split()))
def I(): return int(sys.stdin.readline())
def LS(): return sys.stdin.buffer.readline().rstrip().decode('utf-8').split()
def S(): return sys.stdin.buffer.readline().rstrip().decode('utf-8')
def IR(n): return [I() for i in range(n)]
def LIR(n): return [LI() for i in range(n)]
def SR(n): return [S() for i in range(n)]
def LSR(n): return [LS() for i in range(n)]
def SRL(n): return [list(S()) for i in range(n)]
def MSRL(n): return [[int(j) for j in list(S())] for i in range(n)]
mod = 1000000007



class UnionFind:
    def __init__(self, n):
        
        
        self.table = [-1] * n
        self.size = [1] * n
        

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

    def get_size(self, x):
        r = self.root(x)
        return self.size[r]

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

    def union(self, x, y):
        r1 = self.root(x)
        r2 = self.root(y)
        if r1 == r2:
            return
        
        d1 = self.table[r1]
        d2 = self.table[r2]
        if d1 <= d2:
            self.table[r2] = r1
            self.size[r1] += self.size[r2]
            if d1 == d2:
                self.table[r1] -= 1
        else:
            self.table[r1] = r2
            self.size[r2] += self.size[r1]
        

n, k = LI()
P = LI()
C = LI()
U = UnionFind(n)
for i in range(n):
    U.union(P[i] - 1, i)

D = defaultdict(int)
for i in range(n):
    D[U.root(i)] += C[i]

ans = -INF
k -= 1
for j in range(n):
    now = P[j] - 1
    r = D[U.root(now)]
    m = U.get_size(now)
    ret = C[now]
    ans = max(ans, ret)
    if k // m and r >= 0:
        ret += k // m * r
        ans = max(ans, ret)
        for l in range(k % m):
            now = P[now] - 1
            ret += C[now]
            ans = max(ans, ret)
    else:
        for l in range(min(m, k)):
            now = P[now] - 1
            ret += C[now]
            ans = max(ans, ret)

print(ans)

Solution (Python):
INF=10**9
f=lambda:[*map(int,input().split())]
n,k=f()
p,c=f(),f()
p=[*map(lambda x:x-1,p)]
tp=[[*range(n)] for _ in range(n+1)]
tc=[[0]*n for _ in range(n+1)]
lt=[0]*n
lc=[0]*n
for i in range(n):
  for j in range(n):
    t=p[tp[i][j]]
    tp[i+1][j]=t
    tc[i+1][j]=tc[i][j]+c[t]
    if t==j and lt[j]==0:
      lt[j]=i+1
      lc[j]=tc[i+1][j]
a=-INF
for i in range(n):
  if lc[i]<1 or k<=lt[i]:
    for j in range(min(lt[i],k)):
      a=max(a,tc[j+1][i])
  else:
    for j in range(lt[i]):
      t=k//lt[i]*lc[i]+tc[j+1][i]
      if k%lt[i]<j+1: t-=lc[i]
      a=max(a,t)
print(a)

Solution (Python):
import sys, re
from collections import deque, defaultdict, Counter
from math import ceil, sqrt, hypot, factorial, pi, sin, cos, tan, asin, acos, atan, radians, degrees, log2, gcd
from itertools import accumulate, permutations, combinations, combinations_with_replacement, product, groupby
from operator import itemgetter, mul
from copy import deepcopy
from string import ascii_lowercase, ascii_uppercase, digits
from bisect import bisect, bisect_left, insort, insort_left
from heapq import heappush, heappop
from functools import reduce, lru_cache
def input(): return sys.stdin.readline().strip()
def INT(): return int(input())
def MAP(): return map(int, input().split())
def LIST(): return list(map(int, input().split()))
def TUPLE(): return tuple(map(int, input().split()))
def ZIP(n): return zip(*(MAP() for _ in range(n)))
sys.setrecursionlimit(10 ** 9)
INF = float('inf')
mod = 10 ** 9 + 7 

from decimal import *



N, K = MAP()
P = LIST()
C = LIST()

check = [0]*N 
score = []

i = 0
while 1:
	while i < N and check[i]:
		i += 1
	if i == N:
		break

	tmp = []
	while check[i] == 0:
		check[i] = 1
		i = P[i]-1
		tmp.append(C[i])
	score.append(tmp)

ans = -INF
for x in score:
	x_acc = list(accumulate([0] + x*3))
	n = len(x)

	if x_acc[n] <= 0:
		tmp_ans = 0
		l = min(K, n)
	else:
		tmp_ans = x_acc[n]*(max(0, K//n-1))
		l = min(K%n+n, K)
	tmp_max = -INF

	for i, j in combinations(range(3*n+1), 2):
		if j-i <= l:
			if tmp_max < x_acc[j]-x_acc[i]:
				tmp_max = x_acc[j]-x_acc[i]
	tmp_ans += tmp_max
	ans = max(ans, tmp_ans)

print(ans)

Solution (Python):
from collections import defaultdict, deque, Counter
from heapq import heappush, heappop, heapify
import math
import bisect
import random
from itertools import permutations, accumulate, combinations, product
import sys
from pprint import pprint
from copy import deepcopy
import string
from bisect import bisect_left, bisect_right
from math import factorial, ceil, floor
from operator import mul
from functools import reduce
from pprint import pprint


sys.setrecursionlimit(2147483647)
INF = 10 ** 20
def LI(): return list(map(int, sys.stdin.readline().split()))
def I(): return int(sys.stdin.readline())
def LS(): return sys.stdin.buffer.readline().rstrip().decode('utf-8').split()
def S(): return sys.stdin.buffer.readline().rstrip().decode('utf-8')
def IR(n): return [I() for i in range(n)]
def LIR(n): return [LI() for i in range(n)]
def SR(n): return [S() for i in range(n)]
def LSR(n): return [LS() for i in range(n)]
def SRL(n): return [list(S()) for i in range(n)]
def MSRL(n): return [[int(j) for j in list(S())] for i in range(n)]
mod = 1000000007



class UnionFind:
    def __init__(self, n):
        
        
        self.table = [-1] * n
        self.size = [1] * n
        

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

    def get_size(self, x):
        r = self.root(x)
        return self.size[r]

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

    def union(self, x, y):
        r1 = self.root(x)
        r2 = self.root(y)
        if r1 == r2:
            return
        
        d1 = self.table[r1]
        d2 = self.table[r2]
        if d1 <= d2:
            self.table[r2] = r1
            self.size[r1] += self.size[r2]
            if d1 == d2:
                self.table[r1] -= 1
        else:
            self.table[r1] = r2
            self.size[r2] += self.size[r1]
        

n, k = LI()
P = LI()
C = LI()
U = UnionFind(n)
for i in range(n):
    U.union(P[i] - 1, i)

D = defaultdict(int)
for i in range(n):
    D[U.root(i)] += C[i]

ans = -INF
k -= 1
for j in range(n):
    r = D[U.root(j)]
    m = U.get_size(j)
    now = P[j] - 1
    ret_max = C[now]
    ret = C[now]
    if k // m and r >= 0:
        for l in range(k % m):
            now = P[now] - 1
            ret += C[now]
            ret_max = max(ret_max, ret)
        ret_max += k // m * r
    else:
        for l in range(min(m, k)):
            now = P[now] - 1
            ret += C[now]
            ret_max = max(ret_max, ret)
    ans = max(ans, ret_max)

print(ans)

Solution (Python):
n, k =map(int, input().split())
p = list(map(int, input().split()))
c = list(map(int, input().split()))
roop = []
seen = [0 for  _ in range(n)]
count = 0
for i in range(n):
    if seen[i]>0:
        continue
    else:
        count+=1
        seen[i] = count
        roop.append([c[i]])
        t = i
        while i!=p[t]-1:
            seen[p[t]-1]=count
            roop[-1].append(c[p[t]-1])
            t = p[t]-1


ans = max(c)

for i in roop:
    
    
    s = sum(i)
    ii = i+i
    
    if len(i)>=k:
        for j in range(1, k+1):
            temp = sum(ii[:j])
            for l in range(len(i)):
                if l!=0:
                    temp+=ii[l+j-1]
                    temp-=ii[l-1]
                    
                
                ans  = max(ans, temp)
    else:
        for j in range(1, len(i)+1):
            temp=  sum(ii[:j])
            for l in range(len(i)):
                if l != 0:
                    temp+=ii[l+j-1]
                    temp-=ii[l-1]
                
                if s>0:
                    temp1 = temp+s*((k-j)//len(i))
                else:
                    temp1 = temp
                
                
                ans  = max(ans, temp)
                ans  = max(ans, temp1)
            
print(ans)

Solution (Python):
import sys, re
from collections import deque, defaultdict, Counter
from math import ceil, sqrt, hypot, factorial, pi, sin, cos, tan, asin, acos, atan, radians, degrees, log2, gcd
from itertools import accumulate, permutations, combinations, combinations_with_replacement, product, groupby
from operator import itemgetter, mul
from copy import deepcopy
from string import ascii_lowercase, ascii_uppercase, digits
from bisect import bisect, bisect_left, insort, insort_left
from heapq import heappush, heappop
from functools import reduce, lru_cache
def input(): return sys.stdin.readline().strip()
def INT(): return int(input())
def MAP(): return map(int, input().split())
def LIST(): return list(map(int, input().split()))
def TUPLE(): return tuple(map(int, input().split()))
def ZIP(n): return zip(*(MAP() for _ in range(n)))
sys.setrecursionlimit(10 ** 9)
INF = float('inf')
mod = 10 ** 9 + 7 

from decimal import *



N, K = MAP()
P = LIST()
C = LIST()

check = [0]*N 
score = []

i = 0
while 1:
	while i < N and check[i]:
		i += 1
	if i == N:
		break

	tmp = []
	while check[i] == 0:
		check[i] = 1
		i = P[i]-1
		tmp.append(C[i])
	score.append(tmp)

ans = -INF
for x in score:
	x_acc = list(accumulate([0] + x + x))
	n = len(x)
	tmp_max = -INF

	cnt = 0
	p, q = 0, 0
	for i, j in combinations(range(2*n+1), 2):
		if j-i <= min(K, n):
			if tmp_max < x_acc[j]-x_acc[i]:
				tmp_max = x_acc[j]-x_acc[i]
				cnt = j-i
				p, q = i, j


	tmp_ans = -INF
	lis = x[(q-1)%n+1:]+x[:(q-1)%n+1]

	if 0 >= x_acc[n]:
		tmp_ans = tmp_max

	else:
		if cnt <= K%n:
			tmp_ans = x_acc[n]*(K//n) + tmp_max
		else:
			tmp_max2 = 0
			for i, j in combinations(range(2*n+1), 2):
				if j-i <= K%n:
					if tmp_max2 < x_acc[j]-x_acc[i]:
						tmp_max2 = x_acc[j]-x_acc[i]
			tmp_ans = max(x_acc[n]*(K//n-1)+tmp_max, x_acc[n]*(K//n) + tmp_max2)

	ans = max(ans, tmp_ans)

print(ans)

Solution (Python):

def main():
    N, K = map(int, input().split())
    P = [int(x) - 1 for x in input().split()]
    C = [int(x) for x in input().split()]

    ans = -10 ** 9
    for start in range(N):
        
        now = start
        loop = []
        total = 0
        while now != start or not loop:
            loop.append(C[now])
            now = P[now]
            total += C[now]
        
        length = len(loop)
        
        
        
        
        
        
        
        t = 0
        for i in range(length):
            t += loop[i]
            if i + 1 > K:
                break
            now = t
            if total > 0:
                e = (K - (i + 1)) // length
                now += total * e
            ans = max(ans, now)
    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()))
for i in range(n):
    p[i] -= 1


ans = -int(1e18)
for si in range(n):
    x = si
    s = []
    opscore = 0 
    while True:
        x = p[x]
        opscore += c[x]
        s.append(c[x])
        if x == si: 
            break

    oplen = len(s)
    t = 0 
    for i in range(oplen):
        t += s[i]
        if i+1 > k:
            break
        now = t 
        if opscore > 0:
            e = (k-(i+1))//oplen
            now += opscore * e 
        ans = max(ans, now)

print(ans)

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

ans = -(10 ** 18)

for si in range(N):
    x = si
    loop = []
    total = 0
    while 1:
        x = P[x]
        loop.append(C[x])
        total += C[x]
        if x == si:
            break
    T = len(loop)  
    tmp = 0
    for i in range(T):
        tmp += loop[i]
        if K < i + 1:
            break
        now = tmp
        if total > 0:  
            loop_times = (K - (i + 1)) // T  
            now += total * loop_times
        ans = max(ans, now)

print(ans)

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**10
    
    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 = k%count+count
        else:
            a = 0
            num = min(k, count)

        for _ in range(num):
            start = p[start]-1
            a += c[start]
            ans = max(a, ans)
    print(int(ans))

main()

Solution (Python):
def solve():
    from collections import defaultdict
    class UnionFind():
        def __init__(self, n):
            self.n = n
            self.par = [-1] * n

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

        def unite(self, x, y):
            x = self.find(x)
            y = self.find(y)

            if x == y:
                return

            if self.par[x] > self.par[y]:
                x, y = y, x

            self.par[x] += self.par[y]
            self.par[y] = x

        def size(self, x):
            return -self.par[self.find(x)]

        def same(self, x, y):
            return self.find(x) == self.find(y)

    n, k = map(int, input().split())
    p = list(map(int, input().split()))
    c = list(map(int, input().split()))
    mp = defaultdict(int)
    uf = UnionFind(n)

    for i in range(n):
        uf.unite(i, p[i] - 1)

    for i in range(n):
        mp[uf.find(i)] += c[i]

    ans = -10 ** 14
    for i in range(n):
        roop = uf.size(i) 
        times = (k - 1) // roop if mp[uf.find(i)] > 0 else 0
        over = max(min(roop, k - roop * times), 1)
        tmp = 0
        s = -10 ** 10
        idx = i
        for j in range(over):
            tmp += c[idx]
            s = max(s, tmp)
            idx = p[idx] - 1
        s += times * mp[uf.find(i)]
        ans = max(ans, s)
    print(ans)


solve()