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

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

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

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

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

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

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

Difficulty: interview

Starter code:

Solutions:
import numpy as np

def __starting_point():

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

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

	for n in range(N):
		v = n

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

				v = P[v]
				if cycleIDs[v] != -1:
					# サイクル終了
					# ループを含めない最大の処理回数
					procCnt = K % len( currentCycleCosts )
					# それで足りてるのかわからないが、Last2周分は、ループするものとして確定させない
					# その部分は、ちゃんと計算する
					# -------------------------------------------------
					# 4 101
					# 2 3 4 1
					# 50 -49 -50 50
					# 上記のようなパターンの場合、
					# 最大25回ループ + 1回処理可能だが、その場合、25 + 50 = 75
					# 24回ループ + 2回処理でやめると、124になる
					# 無条件でループする回数は、最大の回数だけでなく、
					# 最大の回数-1も考慮の必要あり
					# -------------------------------------------------
					# あるいは、割り切れて、尚且つサイクル合計がマイナスのパターンで、最低１個は処理するのにもここで対応
					if len( currentCycleCosts ) + procCnt <= K:
						procCnt += len( currentCycleCosts )

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



	# scores = []
	# procCnt = 0
	ans = -10 ** 9
	for procCnt, currentCycleSize, currentCycleCosts in cycleInfs:

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

		# このサイクルに属する全頂点分をまとめて計算する
		for i in range(currentCycleSize):
			# scores.append( np.roll( currentCycleCosts, i )[:procCnt].cumsum().max() + loopScore )
			# print(np.roll( currentCycleCosts, i ).cumsum()[:procCnt])
			ans = max( ans, np.roll( currentCycleCosts, i ).cumsum()[:procCnt].max() + loopScore )


	print(ans)
	# print(max(scores))

__starting_point()

import numpy as np


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

    seen = set()
    loop_list = []
    for start in range(n):
        v = start
        loop = []
        while v not in seen:
            seen.add(v)
            loop.append(c[v])
            v = p[v]
        seen.add(v)
        if loop:
            loop_list.append(np.array(loop))

    ans = min(c)
    for loop in loop_list:
        loop_len = len(loop)
        loop_num = k // loop_len
        loop_mod = k % loop_len
        loop_sum = sum(loop)
        table = np.zeros((loop_len, loop_len), dtype=int)
        table[0] = loop.cumsum()
        table[:, -1] = loop_sum
        for i in range(loop_len - 1):
            table[i + 1, :-1] = (table[i] - loop[i])[1:]
        ans = max(table[:, :min(loop_len, k)].max(), ans)
        if loop_num > 0:
            ans = max(loop_sum * (loop_num - 1) + table[:, :loop_len].max(), ans)
            if loop_mod > 0:
                ans = max(loop_sum * loop_num + table[:, :loop_mod].max(), ans)
    print(ans)


def __starting_point():
    main()

__starting_point()

import sys

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

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

solve()

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

# Date [ 2020-08-15 21:53:58 ]
# Problem [ d.py ]
# Author Koki_tkg

import sys;      from decimal import Decimal
import math;     from itertools import combinations, product, accumulate
import bisect;   from collections import Counter, deque, defaultdict

# sys.setrecursionlimit(10 ** 6)
MOD = 10 ** 6 + 7
INF = 10 ** 9
PI = 3.14159265358979323846

def read_str():      return sys.stdin.readline().strip()
def read_int():      return int(sys.stdin.readline().strip())
def read_ints():     return map(int, sys.stdin.readline().strip().split())
def read_str_list(): return list(sys.stdin.readline().strip().split())
def read_int_list(): return list(map(int, sys.stdin.readline().strip().split()))
def lcm(a: int, b: int) -> int: return (a * b) // math.gcd(a, b)

def Main():
    n, k = read_ints()
    p = read_int_list()
    c = read_int_list()
    loop_list = []
    visit = [False] * n

    # 閉路を探してloop_listに格納
    for i in range(n):
        if visit[i]:
            continue

        visit[i] = True
        now = i
        loop_tmp = []

        while True:
            now = p[now] - 1
            visit[now] = True
            loop_tmp.append(c[now])
            if visit[p[now] - 1]:
                loop_tmp.append(c[p[now] - 1])
                break
        loop_list.append(loop_tmp)

    #print(loop_list)
    ans = -10 ** 18

    #loopごとに全部試す
    for loop in loop_list:
        length = len(loop)
        score = sum(loop)
        if k > length:
            if score > 0:
                ans = max(ans, (k // length) * score + search_max_score(loop, k % length, length), (k // length - 1) * score + search_max_score(loop, length, length))
            else:
                ans = max(ans, search_max_score(loop, length, length))
        else:
            ans = max(ans, search_max_score(loop, k, length))
    
    print(ans)


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

if __name__ ==  '__main__':
    Main()

import numpy as np


def parse():
    _, k = list(map(int, input().split()))
    p = list(map(int, input().split()))
    c = list(map(int, input().split()))
    pc = {i: (pi - 1, ci) for i, (pi, ci) in enumerate(zip(p, c))}
    return k, pc


def read_split():
    k, pc = parse()
    lst = [[]]
    lst[0].append(pc.pop(0))
    while True:
        if not pc:
            break
        p, _ = lst[-1][-1]
        if p in pc:
            pcj = pc.pop(p)
            lst[-1].append(pcj)
        else:
            j = next(iter(list(pc.keys())))
            pcj = pc.pop(j)
            lst.append([pcj])
    return k, [np.array([ls[1] for ls in lst_], dtype=np.long) for lst_ in lst]


def inner(n, k, s, sim):
    if sim.shape[1] == 1:
        return sim.max()
    if k < n or s <= 0:
        return sim.max()
    div = k // n
    mod = k % n
    if mod == 0:
        return s * (div - 1) + sim.max()
    else:
        return s * div + sim[:, :mod].max()


def main():
    k, data_set = read_split()
    result = min([d.min() for d in data_set])
    for data in data_set:
        n = data.size
        rep = np.repeat(data[None], 2, axis=0).flatten()
        sim = np.array([np.cumsum(rep[i:i+min(k, n)]) for i in range(n)])
        cand = inner(n, k, data.sum(), sim)
        result = max(result, cand)
    print(result)


def __starting_point():
    main()

__starting_point()

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

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


class SegmentTree():
    def __init__(self, array, f, ti):
        """
        Parameters
        ----------
        array : list
            to construct segment tree from
        f : func
            binary operation of the monoid
        ti : 
            identity element of the monoid
        """
        self.f = f
        self.ti = ti
        self.n = n = 2**(len(array).bit_length())
        self.dat = dat = [ti] * n + array + [ti] * (n - len(array))
        for i in range(n - 1, 0, -1):  # build
            dat[i] = f(dat[i << 1], dat[i << 1 | 1])

    def update(self, p, v):  # set value at position p (0-indexed)
        f, n, dat = self.f, self.n, self.dat
        p += n
        dat[p] = v
        while p > 1:
            p >>= 1
            dat[p] = f(dat[p << 1], dat[p << 1 | 1])

    def operate_right(self, p, v):  # apply operator from the right side
        f, n, dat = self.f, self.n, self.dat
        p += n
        dat[p] = f(dat[p], v)
        while p > 1:
            p >>= 1
            dat[p] = f(dat[p << 1], dat[p << 1 | 1])

    def operate_left(self, p, v):  # apply operator from the left side
        f, n, dat = self.f, self.n, self.dat
        p += n
        dat[p] = f(v, dat[p])
        while p > 1:
            p >>= 1
            dat[p] = f(dat[p << 1], dat[p << 1 | 1])

    def query(self, l, r):  # result on interval [l, r) (0-indexed)
        f, ti, n, dat = self.f, self.ti, self.n, self.dat
        vl = vr = ti
        l += n
        r += n
        while l < r:
            if l & 1:
                vl = f(vl, dat[l])
                l += 1
            if r & 1:
                r -= 1
                vr = f(dat[r], vr)
            l >>= 1
            r >>= 1
        return f(vl, vr)


ans = -10**20
se = set()
for start in range(N):
    if start in se:
        continue
    now = start
    scores = []
    while True:
        if now in se:
            break
        se.add(now)
        scores += [C[now]]
        now = P[now]
    cyclelen = len(scores)
    cum = list(itertools.accumulate(scores * 3))
    st = SegmentTree(cum, max, -10**20)
    cycle, residue = divmod(K, cyclelen)
    ans = max([ans] + [
        st.query(start2 + 1, start2 + 1 + min(cyclelen, K)) - cum[start2]
        for start2 in range(cyclelen)
    ])
    if cum[-1] > 0 and cycle > 0:
        v = cum[-1] * cycle // 3 + max(
            st.query(0, start2 + residue + 1) - cum[start2]
            for start2 in range(cyclelen, 2 * cyclelen))
        ans = max(ans, v)
print(ans)


from itertools import accumulate

def main():
  n,k=list(map(int,input().split()))
  P=[int(x)-1 for x in input().split()]
  C=[int(x) for x in input().split()]
  F=[False]*n

  a=-10**9
  for i in range(n):
    if F[i]:
      continue

    p,F[i],L=i,True,[C[i]]
    while P[p]!=i:
      p=P[p]
      F[p]=True
      L.append(C[p])
    t,l=sum(L),len(L)
    s=t*(k//l-1) if t>0 else 0

    m,L=-10**9,L*3
    u=k%l+l if t>0 else min(k,l)
    for j in range(l):
      m=max(m,max(accumulate(L[j:j+u])))

    a=max(s+m,a)

  print(a)

main()


import numpy as np
 
n, k = map(int, input().split())
p = list(map(int, input().split()))
c = list(map(int, input().split()))
 
cycles, check = [], [False]*n
for pi in p:
    if not check[pi-1]:
        curr, cycle = pi, []
        check[pi-1] = True
        while pi != p[curr-1]:
            check[curr-1] = True
            cycle.append(c[curr-1])
            curr = p[curr-1]
        check[curr-1] = True
        cycles.append(cycle + [c[curr-1]])

scores = []
for cycle in (np.array(cycle) for cycle in cycles):
    for i in range(cycle.size):
        cum = np.roll(cycle, i).cumsum()
        if cum[-1] > 0 and k > cycle.size:
            scores.append(cum[-1]*(k//cycle.size-1) + np.concatenate([cum, cum[:k % cycle.size]+cum[-1]]).max())
        else:
            scores.append(cum[:min(k, cum.size)].max())

print(max(scores))

import numpy as np


def parse():
    n, k = list(map(int, input().split()))
    p = list(map(int, input().split()))
    c = list(map(int, input().split()))
    pc = {i: (pi - 1, ci) for i, (pi, ci) in enumerate(zip(p, c))}
    return k, pc


def split_simple():
    k, pc = parse()
    lst = [[]]
    lst[0].append(pc.pop(0))
    while True:
        if not pc:
            break
        p, _ = lst[-1][-1]
        if p in pc:
            pcj = pc.pop(p)
            lst[-1].append(pcj)
        else:
            j = next(iter(list(pc.keys())))
            pcj = pc.pop(j)
            lst.append([pcj])
    return k, [np.array([ls[1] for ls in lst_], dtype=np.long) for lst_ in lst]


def inner(n, k, s, sim):
    # print(sim)
    # print(s)
    if sim.shape[1] == 1:
        return sim.max()
    if k < n or s <= 0:
        return sim.max()
    div = k // n
    mod = k % n
    # print(k, n, div, mod)
    if mod == 0:
        return max(s * div, s * (div - 1) + sim.max())
    try:
        return max(s * div + sim[:, :mod].max(), s * (div - 1) + sim[:, :mod].max())
    except ValueError:
        print(mod)
        print(sim)
        print((sim.shape))
        raise


def main():
    k, data_set = split_simple()
    result = min([d.min() for d in data_set])
    for data in data_set:
        n = data.size
        rep = np.repeat(data[None], 2, axis=0).flatten()
        # sim_ = np.array([[rep[i:i+p].sum()
        #                  for p in range(1, min(k, n) + 1)] for i in range(n)])
        sim = np.array([np.cumsum(rep[i:i+min(k, n)]) for i in range(n)])
        # print((sim == sim_).all())
        cand = inner(n, k, data.sum(), sim)
        result = max(result, cand)
    print(result)


def __starting_point():
    main()

__starting_point()

import sys, math

def calcweight_tree(N_vertices, edges, times, inf):

    """
    edges: [start, dest, cost] -> [cost, start, end]
    """

    distance = 0

    passed = [False] * N_vertices

    travel_max = -inf
    for i in range(N_vertices):
        if(passed[i] == False):
            distance = 0
            left = i
            cost_sum = 0
            costs = []
            min_distance = inf
            while(True):
                dest = edges[left][1]
                cost = edges[dest][0]
                if(passed[dest]==False):
                    #passed[left] = True
                    passed[dest] = True
                    cost_sum += cost
                    costs.append(cost_sum)
                    left = dest
                    if(min_distance > cost):
                        min_distance = cost
                else:
                    period = len(costs)
                    increase_period = cost_sum
                    break
            # 2 period項準備
            remainder = times%period
            cost_minus = [0]
            for j in range(period-1):
                cost_minus.append(costs[j])
            if(increase_period <= 0):
                """
                for j in range(period):
                    costs.append(costs[j]+increase_period)
                maxindex = 0
                maxindex_start = 0
                maxvalue = -inf

                if(remainder==0):
                    remainder += period

                for st in range(period):
                    maxvalue_candidate = max(costs[st:st+period])
                    if(maxvalue_candidate - cost_minus[st] > maxvalue):
                        maxvalue = maxvalue_candidate - cost_minus[st]
                        maxindex = costs[st:st+period].index(maxvalue_candidate) + st
                        maxindex_start = st
                """
                costs_last = []
                # a_0は0なので。そしてこれは最大値を考えるときには数えないので
                remainder2 = remainder % period

                #print("x", costs, increase_period, remainder2)
                """
                for j in range(remainder2, period):
                    costs_last.append(costs[j])
                for j in range(0, remainder2):
                    costs_last.append(costs[j]+increase_period)
                for j in range(period):
                    costs_last.append(costs_last[j]+increase_period)
                """
                for j in range(period):
                    costs_last.append(costs[j])
                for j in range(period):
                    costs_last.append(costs_last[j]+increase_period)
                maxvalue = -inf
                #print(costs_last, cost_minus)
                for j in range(period):
                    maxvalue_candidate = max(costs_last[j:j+period])
                    if(maxvalue_candidate-cost_minus[j] > maxvalue):
                        maxvalue = maxvalue_candidate-cost_minus[j]

                travel_max = max(maxvalue, travel_max)
            else:
                costs_last = []
                # a_0は0なので。そしてこれは最大値を考えるときには数えないので
                remainder2 = remainder % period
                times_period = times//period-1
                add_n = times_period * increase_period
                #print(costs, increase_period, remainder2, times_period, add_n)
                for j in range(remainder2, period):
                    costs_last.append(costs[j]+add_n)
                for j in range(0, remainder2):
                    costs_last.append(costs[j]+add_n+increase_period)
                for j in range(period):
                    costs_last.append(costs_last[j]+increase_period)
                maxvalue = -inf
                #print(costs_last, cost_minus)
                for j in range(period):
                    maxvalue_candidate = max(costs_last[j:j+period])
                    if(maxvalue_candidate-cost_minus[j] > maxvalue):
                        maxvalue = maxvalue_candidate-cost_minus[j]
                travel_max = max(maxvalue, travel_max)






    return travel_max







def __starting_point():
    """
    N = int( input().strip() )
    Length = list( map(int, input().strip().split() ) )

    edges = [ [] for _ in range(N+2) ]
    for i in range(N):
        edges[0].append([0, i]) #[cost, edge]
    for i in range(1, N+1):
        edges[i].append([0, N+1])
    for i in range(N):
        edges[i].append([ CList[i]*(-1), PList[i] ])
    """
    N, K= list(map(int, input().strip().split() ))
    PList = list( map(int, input().strip().split() ) )
    CList = list( map(int, input().strip().split() ) )
    inf = 10**10


    N_vertices = N

    edges3 = []
    costs = []
    for i in range(N):
        edges3.append([ CList[i], PList[i]-1 ])

    weight = calcweight_tree(N_vertices, edges3, K, inf)

    #weight= calcweight_bellman_ford(N_vertices, 0, edges3, K+2, cost, inf)


    print( weight)

__starting_point()

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


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

def dfs(G, v, p):
    seen[v] = True
    sc.append(c[v])

    for nv in G[v]:
        if nv == p:
            continue
        if seen[nv]:
            pos[0] = nv
            return

        dfs(G, nv, v)
        if pos[0] != -1:
            return


G = [[] for _ in range(n)]
for i in range(n):
    G[i].append(p[i]-1)

seen = [False]*n
ans = -float('inf')
for i in range(n):
    if seen[i] == False:
        pos = [-1]
        sc = []
        dfs(G, i, -1)

        if sc:
            sumsc = sum(sc)
            lenc = len(sc)
            for j in range(lenc):
                if j != 0:
                    sc = sc[1:] + [sc[0]]
                ac = list(accumulate(sc))
                
                if sumsc <= 0:
                    ans = max(ans, max(ac[:min(k, lenc)]))
                else:
                    if k%lenc == 0:
                        ans = max(ans, ac[-1]*(k//lenc - 1) + max(ac))
                    else:
                        ans = max(ans, ac[-1]*(k//lenc) + max(ac[:k%lenc]))
print(ans)

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):
            a += c[start]
            start=p[start]-1
            ans=max(a,ans)
    print(ans)
main()

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):
            a += c[start]
            start=p[start]-1
            ans=max(a,ans)
    print(ans)
def __starting_point():
    main()
__starting_point()

import sys
input = sys.stdin.readline



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

    print(ans)
        
    


    
    
def __starting_point():
    main()

__starting_point()

# import numpy as np
import itertools

def __starting_point():

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

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

	for n in range(N):
		v = n

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

				v = P[v]
				if cycleIDs[v] != -1:
					# サイクル終了
					# ループを含めない最大の処理回数
					procCnt = K % len( currentCycleCosts )
					# それで足りてるのかわからないが、Last2周分は、ループ合計がプラスでも必ずしもループするとは限らない
					# その部分は、ちゃんと計算する
					# -------------------------------------------------
					# 4 101
					# 2 3 4 1
					# 50 -49 -50 50
					# 上記のようなパターンの場合、
					# 最大25回ループ + 1回処理可能だが、その場合、25 + 50 = 75
					# 24回ループ + 2回処理でやめると、124になる
					# 無条件でループする回数は、ループ可能な最大の回数-1らしい
					# -------------------------------------------------
					# 割り切れて、尚且つサイクル合計がマイナスのパターンで、最低１個は処理するのにもここで対応
					if len( currentCycleCosts ) + procCnt <= K:
						procCnt += len( currentCycleCosts )

					cycleInfs.append( ( procCnt, len(currentCycleCosts), currentCycleCosts * 3 ) )
					cycleID += 1
					break



	# scores = []
	# procCnt = 0
	ans = -10 ** 9
	for procCnt, currentCycleSize, currentCycleCosts in cycleInfs:

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

		# このサイクルに属する全頂点分をまとめて計算する
		for i in range(currentCycleSize):
			# print(np.roll( currentCycleCosts, i ).cumsum()[:procCnt])
			score = max( itertools.accumulate( currentCycleCosts[i:i+procCnt] ) )
			if ans < score + loopScore:
				ans = score + loopScore
			# ans = max( ans, score + loopScore )


	print(ans)
	# print(max(scores))

__starting_point()

from numba import jit
@jit
def main():
  n,k=list(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()


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


def solve(n, k, ppp, ccc):
    NINF = -(10 ** 18)
    ans = NINF

    checked = [False] * n
    for s in range(n):
        if checked[s] == True:
            continue
        checked[s] = True
        scores = [ccc[ppp[s]]]
        v = ppp[s]
        while v != s:
            scores.append(ccc[ppp[v]])
            checked[v] = True
            v = ppp[v]

        l = len(scores)
        d, m = divmod(k, l)
        loop = sum(scores)

        if d > 0:
            d -= 1
            m += l

        scores += scores * 2
        scores.insert(0, 0)
        acc = list(accumulate(scores))

        base = max(0, loop * d)

        range_max = [-a for a in acc[1:m + 1]]
        available_max = Counter(range_max)
        heapify(range_max)
        for i in range(l):
            while available_max[range_max[0]] == 0:
                heappop(range_max)
            ans = max(ans, base - range_max[0] - acc[i])
            old = -acc[i + 1]
            new = -acc[i + m + 1]
            available_max[old] -= 1
            available_max[new] += 1
            heappush(range_max, new)

    return ans


n, k = list(map(int, input().split()))
ppp = list(map(int, input().split()))
ppp = [p - 1 for p in ppp]
ccc = list(map(int, input().split()))

print((solve(n, k, ppp, ccc)))


from math import inf
from sys import setrecursionlimit

setrecursionlimit(10**4)

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

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

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

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

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

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

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

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



g = Graph(N)
print(g.maxscore())

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

import numpy as np
n, k = map(int, input().split())
p = list(map(int, input().split()))
c = list(map(int, input().split()))
 
cycles, check = [], [False]*n
for pi in p:
    if not check[pi-1]:
        curr, cycle = pi, []
        check[pi-1] = True
        while pi != p[curr-1]:
            check[curr-1] = True
            cycle.append(c[curr-1])
            curr = p[curr-1]
        check[curr-1] = True
        cycles.append(cycle + [c[curr-1]])

scores = []
for cycle in (np.array(cycle) for cycle in cycles):
    for i in range(cycle.size):
        cum = np.roll(cycle, i).cumsum()
        if cum[-1] > 0 and k > cycle.size:
            scores.append(cum[-1]*(k//cycle.size-1) + np.concatenate([cum, cum[:k % cycle.size]+cum[-1]]).max())
        else:
            scores.append(cum[:min(k, cum.size)].max())
print(max(scores))

from numba import jit
@jit
def main():
  n,k=list(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: #ループ部分. iに戻る直前まで続ける.
      start=p[start]-1
      count+=1
      val+=c[start]
    start=i
    # この時点でvalは1ループのスコア合計, カウントは1ループのsizeになっている
    '''
    以下の基本的な方針は
    - 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  # 最後に余りのk%count回ぶんだけでなく1周半ぶんは試したいので(ループ余りではk%count回しか移動できないわけではない)
      ans=max(a,ans)
      num=count+k%count
    else:
      a=0
      num=min(k,count)  # 1周以内におさめたい. k<countという非常に限られた場合のみk回までの移動になることを考慮。
    for _ in range(num):
      start=p[start]-1
      a+=c[start]
      ans=max(a,ans)
  print(ans)
main()


import numpy as np

def __starting_point():
	N,K = list(map(int,input().split()))
	P = [ int(p)-1 for p in input().split() ]
	C = list(map(int,input().split()))
	cycleIDs = np.full( N, -1, np.int64 )
	cycleInfs = []
	cycleID = 0
	procCnt = 0
	for n in range(N):
		v = n
		if cycleIDs[v] != -1:
			continue
		else:
			currentCycleCosts = []
			while True:
				currentCycleCosts.append( C[v] )
				cycleIDs[v] = cycleID

				v = P[v]
				if cycleIDs[v] != -1:
					procCnt = K % len( currentCycleCosts )
					if len( currentCycleCosts ) + procCnt <= K:
						procCnt += len( currentCycleCosts )
					cycleInfs.append( ( procCnt, len(currentCycleCosts), np.array( currentCycleCosts + currentCycleCosts ) ) )
					cycleID += 1
					break
	ans = -10 ** 9
	for procCnt, currentCycleSize, currentCycleCosts in cycleInfs:
		loopScore = 0
		if np.sum(currentCycleCosts) > 0:
			cycleLoopCnt =  ( K - procCnt ) // currentCycleSize
			loopScore = cycleLoopCnt * np.sum(currentCycleCosts[:currentCycleSize])

		for i in range(currentCycleSize):
			ans = max( ans, np.roll( currentCycleCosts, i ).cumsum()[:procCnt].max() + loopScore )

	print(ans)

__starting_point()

import sys

class SWAG:
    def __init__(self):
        self.fold_l = []
        self.r = []
        self.fold_r = ~(1 << 60)
    def push(self, a):
        if self.fold_r < a:
            self.fold_r = a
        self.r.append(a)
    def pop(self):
        if not self.fold_l:
            self.r.reverse()
            self.fold_l = self.r
            self.r = []
            self.fold_r = ~(1 << 60)
            fold_l = self.fold_l
            for i in range(len(fold_l) - 1):
                if fold_l[i + 1] < fold_l[i]:
                    fold_l[i + 1] = fold_l[i]
        self.fold_l.pop()
    def get(self):
        if not self.fold_l:
            return self.fold_r
        elif not self.r:
            return self.fold_l[-1]
        else:
            return max(self.fold_l[-1], self.fold_r)

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

if max(c) < 0:
    print((max(c)))
    return

ans = 0
used = [False] * n
for i in range(n):
    if used[i]:
        continue

    # ループを取り出す
    loop = []
    at = i
    while not used[at]:
        loop.append(c[at])
        used[at] = True
        at = p[at]

    siz = len(loop)
    cusum = [0] + loop * 3
    for i in range(siz * 3):
        cusum[i + 1] += cusum[i]
    sum = max(0, cusum[siz])

    # k % 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

    # k % siz + siz 回以下での最大
    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)


# import numpy as np
import itertools

def __starting_point():

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

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

	for n in range(N):
		v = n

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

				v = P[v]
				if cycleIDs[v] != -1:
					# サイクル終了
					# ループを含めない最大の処理回数
					procCnt = K % len( currentCycleCosts )
					# それで足りてるのかわからないが、Last2周分は、ループ合計がプラスでも必ずしもループするとは限らない
					# その部分は、ちゃんと計算する
					# -------------------------------------------------
					# 4 101
					# 2 3 4 1
					# 50 -49 -50 50
					# 上記のようなパターンの場合、
					# 最大25回ループ + 1回処理可能だが、その場合、25 + 50 = 75
					# 24回ループ + 2回処理でやめると、124になる
					# 無条件でループする回数は、ループ可能な最大の回数-1らしい
					# -------------------------------------------------
					# 割り切れて、尚且つサイクル合計がマイナスのパターンで、最低１個は処理するのにもここで対応
					if len( currentCycleCosts ) + procCnt <= K:
						procCnt += len( currentCycleCosts )

					cycleInfs.append( ( procCnt, len(currentCycleCosts), currentCycleCosts * 3 ) )
					cycleID += 1
					break



	# scores = []
	# procCnt = 0
	ans = -10 ** 9
	for procCnt, currentCycleSize, currentCycleCosts in cycleInfs:

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

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


	print(ans)
	# print(max(scores))

__starting_point()

# import numpy as np
import itertools

def __starting_point():

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

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

	for n in range(N):
		v = n

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

				v = P[v]
				if cycleIDs[v] != -1:
					# サイクル終了
					# ループを含めない最大の処理回数
					procCnt = K % len( currentCycleCosts )
					# それで足りてるのかわからないが、Last2周分は、ループ合計がプラスでも必ずしもループするとは限らない
					# その部分は、ちゃんと計算する
					# -------------------------------------------------
					# 4 101
					# 2 3 4 1
					# 50 -49 -50 50
					# 上記のようなパターンの場合、
					# 最大25回ループ + 1回処理可能だが、その場合、25 + 50 = 75
					# 24回ループ + 2回処理でやめると、124になる
					# 無条件でループする回数は、ループ可能な最大の回数-1らしい
					# -------------------------------------------------
					# 割り切れて、尚且つサイクル合計がマイナスのパターンで、最低１個は処理するのにもここで対応
					if len( currentCycleCosts ) + procCnt <= K:
						procCnt += len( currentCycleCosts )

					cycleInfs.append( ( procCnt, len(currentCycleCosts), currentCycleCosts * 3 ) )
					cycleID += 1
					break



	# scores = []
	# procCnt = 0
	ans = -10 ** 9
	for procCnt, currentCycleSize, currentCycleCosts in cycleInfs:

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

		# このサイクルに属する全頂点分をまとめて計算する
		for i in range(currentCycleSize):
			# print(np.roll( currentCycleCosts, i ).cumsum()[:procCnt])
			ans = max( ans, max( itertools.accumulate( currentCycleCosts[i:i+procCnt] ) ) + loopScore )


	print(ans)
	# print(max(scores))

__starting_point()

from itertools import accumulate


def solve(n, k, ppp, ccc):
    NINF = -(10 ** 18)
    ans = NINF

    checked = [False] * n
    for s in range(n):
        if checked[s] == True:
            continue
        checked[s] = True
        scores = [ccc[ppp[s]]]
        v = ppp[s]
        while v != s:
            scores.append(ccc[ppp[v]])
            checked[v] = True
            v = ppp[v]

        l = len(scores)
        d, m = divmod(k, l)
        loop = sum(scores)

        if d > 0:
            d -= 1
            m += l

        scores += scores * 2
        scores.insert(0, 0)
        acc = list(accumulate(scores))
        tmp = max(max(acc[i + 1:i + m + 1]) - acc[i] for i in range(l))
        ans = max(ans, tmp, loop * d + tmp)

    return ans


n, k = list(map(int, input().split()))
ppp = list(map(int, input().split()))
ppp = [p - 1 for p in ppp]
ccc = list(map(int, input().split()))

print((solve(n, k, ppp, ccc)))


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


class SegmentTree():
    def __init__(self, array, f, ti):
        """
        Parameters
        ----------
        array : list
            to construct segment tree from
        f : func
            binary operation of the monoid
        ti : 
            identity element of the monoid
        """
        self.f = f
        self.ti = ti
        self.n = n = 2**(len(array).bit_length())
        self.dat = dat = [ti] * n + array + [ti] * (n - len(array))
        for i in range(n - 1, 0, -1):  # build
            dat[i] = f(dat[i << 1], dat[i << 1 | 1])

    def update(self, p, v):  # set value at position p (0-indexed)
        f, n, dat = self.f, self.n, self.dat
        p += n
        dat[p] = v
        while p > 1:
            p >>= 1
            dat[p] = f(dat[p << 1], dat[p << 1 | 1])

    def operate_right(self, p, v):  # apply operator from the right side
        f, n, dat = self.f, self.n, self.dat
        p += n
        dat[p] = f(dat[p], v)
        while p > 1:
            p >>= 1
            dat[p] = f(dat[p << 1], dat[p << 1 | 1])

    def operate_left(self, p, v):  # apply operator from the left side
        f, n, dat = self.f, self.n, self.dat
        p += n
        dat[p] = f(v, dat[p])
        while p > 1:
            p >>= 1
            dat[p] = f(dat[p << 1], dat[p << 1 | 1])

    def query(self, l, r):  # result on interval [l, r) (0-indexed)
        f, ti, n, dat = self.f, self.ti, self.n, self.dat
        vl = vr = ti
        l += n
        r += n
        while l < r:
            if l & 1:
                vl = f(vl, dat[l])
                l += 1
            if r & 1:
                r -= 1
                vr = f(dat[r], vr)
            l >>= 1
            r >>= 1
        return f(vl, vr)


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


from itertools import accumulate
import sys
sys.setrecursionlimit(10**8)

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

seen = [False]*n
ans = -float('inf')
for i in range(n):
    if not seen[i]:
        sc = []
        stop = i
        while True:
            seen[i] = True
            sc.append(c[i])
            if p[i] == stop:
                break
            i = p[i]

        lens = len(sc)
        for j in range(lens):
            if j != 0:
                sc = sc[1:] + [sc[0]]
            ac = list(accumulate(sc))

            if sum(sc) <= 0:
                ans = max(ans, max(ac[:min(k, lens)]))
            else:
                if k%lens == 0:
                    ans = max(ans, ac[-1]*(k//lens-1) + max(ac))
                else:
                    ans = max(ans, ac[-1]*(k//lens) + max(ac[:k%lens]))
print(ans)

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]
        # 2周分の累積和
        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)


def __starting_point():
    n, k = list(map(int, input().split()))
    p = list([int(x)-1 for x in input().split()])
    c = list(map(int, input().split()))
    solve(n, k, p, c)

__starting_point()

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

# Cを書き換える
C = [0] * N
for i in range(N):
    P[i] -= 1
    C[i] = _c[P[i]]

m = 31 # bit数

# ダブリング
vertex = list()
score = list()
vertex.append(P)
score.append(C)
for b in range(1, m+1):
    p_bth = [0] * N
    c_bth = [0] * N
    for i in range(N):
        p_bth[i] = vertex[b-1][vertex[b-1][i]]
        c_bth[i] = score[b-1][i] + score[b-1][vertex[b-1][i]]
    vertex.append(p_bth)
    score.append(c_bth)

# 桁DP
MIN = -(1 << 63) 
prv = [[MIN, 0] for _ in range(N)]
nxt = [[MIN, MIN] for _ in range(N)] 
for b in range(m, -1, -1):
    for i in range(N):
        if (K >> b) & 1:
            nxt[vertex[b][i]][0] = max(nxt[vertex[b][i]][0], prv[i][0] + score[b][i])
            nxt[vertex[b][i]][1] = max(nxt[vertex[b][i]][1], prv[i][1] + score[b][i])
            nxt[i][0] = max(nxt[i][0], prv[i][0], prv[i][1])
        else:
            nxt[vertex[b][i]][0] = max(nxt[vertex[b][i]][0], prv[i][0] + score[b][i])
            nxt[i][0] = max(nxt[i][0], prv[i][0])
            nxt[i][1] = max(nxt[i][1], prv[i][1])
    prv, nxt = nxt, prv

ans = max(max(x) for x in prv)
if ans == 0:
    ans = max(C)

print(ans)

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


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


def get(K, cycle):
    L = len(cycle)
    T = sum(cycle)

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


def solve():
    # square labelled from 1 to N
    N, K = it()
    P = it()
    C = it()

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

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


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

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


from numba import jit
@jit
def main():
  n,k=list(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()


#!/usr/bin/env python
# coding: utf-8

# In[7]:


from itertools import accumulate


# In[19]:


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


# In[20]:


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


# In[ ]:






# D not completed
# -*- coding: utf-8 -*-
N, K = map(int, input().split())
P_list = list(map(int, input().split()))
C_list = list(map(int, input().split()))

checked_list = [0 for _ in range(N)]
min_INF = -1 * 10 ** 10
max_score = min_INF
for i in range(N):
    if checked_list[i] == 1:
        continue
    posit = i
    loop_list = [posit]
    score_list = []
    for j in range(N):
        posit = P_list[posit] - 1
        if j == 0:
            score_list.append(C_list[posit])
        else:
            score_list.append(score_list[-1] + C_list[posit])
        if posit in loop_list:
            break
        loop_list.append(posit)

    len_loop = len(loop_list)
    max_score_list = max(score_list)
    around_score = score_list[-1]
    temp_score_base = 0
    if around_score > 0 and K // len_loop > 0:
        temp_score_base += (K // len_loop - 1) * around_score
    for k in range(len_loop):
        # print("loop", loop_list)
        # print("score", score_list)
        checked_list[loop_list[k]] = 1
        temp_max_score = temp_score_base
        rest_score = min_INF
        if around_score > 0 and K // len_loop > 0:
            # 最後に1周すべきか
            rest_score = max(max_score_list, max(score_list[:K % len_loop], default=min_INF) + around_score)
            # print(loop_list[k], temp_max_score, K, len_loop, K // len_loop)
        rest_score = max(max(score_list[:min(K, len_loop)]), rest_score)
        temp_max_score = temp_max_score + rest_score
        # print(loop_list[k], temp_max_score, rest_score)
        max_score = max(max_score, temp_max_score)
        # ループ内でずらす
        now_score = score_list.pop(0)
        len_score = len(score_list)
        score_list = [score_list[l] - now_score for l in range(len_score)]
        score_list.append(score_list[-1] + now_score)

print(max_score)


n, k = map(int, input().split())
p = [int(x) - 1 for x in input().split()]
c = [int(x) for x in input().split()]
pow_num = 31
point = [[0] * n for i in range(pow_num)]
point_max = [[0] * n for i in range(pow_num)]
posi = [[0] * n for i in range(pow_num)]

c_set = set(c)
if all([i < 0 for i in c_set]):
    print(max(c_set))
else:
    for i in range(pow_num):
        if i == 0:
            for j in range(n):
                posi[i][j] = p[j]
                point[i][j] = c[p[j]]
            continue
        for j in range(n):
            posi[i][j] = posi[i-1][posi[i-1][j]]
            point[i][j] = point[i-1][j] + point[i-1][posi[i-1][j]]
    for i in range(pow_num):
        if i == 0:
            for j in range(n):
                point_max[i][j] = point[i][j]
            continue
        for j in range(n):
            point_max[i][j] = max(point_max[i-1][j], \
                point[i-1][j] + point_max[i-1][posi[i-1][j]])

    power_count = list()
    for i in range(pow_num):
        if k & (1 << i):
            power_count.append(i)

        ans = 0
        for i in range(n):
            next_posi = i
            cumsum_point = 0
            for posi_idx in power_count:
                if ans < cumsum_point + point_max[posi_idx][next_posi]:
                    ans = cumsum_point + point_max[posi_idx][next_posi]
                cumsum_point += point[posi_idx][next_posi]
                next_posi = posi[posi_idx][next_posi]

    print(ans)

from numba import jit
@jit
def main():
    n, k = list(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()


# import numpy as np
import itertools

def __starting_point():

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

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

	for n in range(N):
		v = n

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

				v = P[v]
				if cycleIDs[v] != -1:
					# サイクル終了
					# ループを含めない最大の処理回数
					procCnt = K % len( currentCycleCosts )
					# それで足りてるのかわからないが、Last2周分は、ループ合計がプラスでも必ずしもループするとは限らない
					# その部分は、ちゃんと計算する
					# -------------------------------------------------
					# 4 101
					# 2 3 4 1
					# 50 -49 -50 50
					# 上記のようなパターンの場合、
					# 最大25回ループ + 1回処理可能だが、その場合、25 + 50 = 75
					# 24回ループ + 2回処理でやめると、124になる
					# 無条件でループする回数は、ループ可能な最大の回数-1らしい
					# -------------------------------------------------
					# 割り切れて、尚且つサイクル合計がマイナスのパターンで、最低１個は処理するのにもここで対応
					if len( currentCycleCosts ) + procCnt <= K:
						procCnt += len( currentCycleCosts )

					cycleInfs.append( ( procCnt, len(currentCycleCosts), currentCycleCosts * 3 ) )
					cycleID += 1
					break



	# scores = []
	# procCnt = 0
	ans = -10 ** 9
	for procCnt, currentCycleSize, currentCycleCosts in cycleInfs:

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

		# このサイクルに属する全頂点分をまとめて計算する
		for i in range(currentCycleSize):
			# print(np.roll( currentCycleCosts, i ).cumsum()[:procCnt])
			score = max( itertools.accumulate( currentCycleCosts[i:i+procCnt] ) )
			if ans < score + loopScore:
				ans = score + loopScore
			# ans = max( ans, score + loopScore )


	print(ans)
	# print(max(scores))

__starting_point()