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

     __init__ """
        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.f self f f self.ti = ti self.ti self ti ti self.n = n = 2**(len(array).bit_length()) self.n self n 2**(len(array).bit_length()) 2 len(array).bit_length() (array).bit_length (array) len array bit_length = n = 2**(len(array).bit_length()) n 2**(len(array).bit_length()) self.dat = dat = [ti] * n + array + [ti] * (n - len(array)) self.dat self dat [ti] * n + array + [ti] * (n - len(array)) [ti] * n + array [ti] * n [ti] ti n array [ti] * (n - len(array)) [ti] ti n - len(array) n len(array) len array = dat = [ti] * n + array + [ti] * (n - len(array)) 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])

     i range(n - 1, 0, -1) range n - 1 n 1 0 -1 dat[i] = f(dat[i << 1], dat[i << 1 | 1]) dat[i] dat i f(dat[i << 1], dat[i << 1 | 1]) f dat[i << 1] dat i << 1 i 1 dat[i << 1 | 1] dat i << 1 | 1 i << 1 i 1 1 self self array array f f ti ti 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])

     update f, n, dat = self.f, self.n, self.dat f self.f self f n self.n self n dat self.dat self dat p += n p n dat[p] = v dat[p] dat p v while p > 1:
            p >>= 1
            dat[p] = f(dat[p << 1], dat[p << 1 | 1])

     p > 1 p 1 p >>= 1 p 1 dat[p] = f(dat[p << 1], dat[p << 1 | 1]) dat[p] dat p f(dat[p << 1], dat[p << 1 | 1]) f dat[p << 1] dat p << 1 p 1 dat[p << 1 | 1] dat p << 1 | 1 p << 1 p 1 1 self self p p v v 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])

     operate_right f, n, dat = self.f, self.n, self.dat f self.f self f n self.n self n dat self.dat self dat p += n p n dat[p] = f(dat[p], v) dat[p] dat p f(dat[p], v) f dat[p] dat p v while p > 1:
            p >>= 1
            dat[p] = f(dat[p << 1], dat[p << 1 | 1])

     p > 1 p 1 p >>= 1 p 1 dat[p] = f(dat[p << 1], dat[p << 1 | 1]) dat[p] dat p f(dat[p << 1], dat[p << 1 | 1]) f dat[p << 1] dat p << 1 p 1 dat[p << 1 | 1] dat p << 1 | 1 p << 1 p 1 1 self self p p v v 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])

     operate_left f, n, dat = self.f, self.n, self.dat f self.f self f n self.n self n dat self.dat self dat p += n p n dat[p] = f(v, dat[p]) dat[p] dat p f(v, dat[p]) f v dat[p] dat p while p > 1:
            p >>= 1
            dat[p] = f(dat[p << 1], dat[p << 1 | 1])

     p > 1 p 1 p >>= 1 p 1 dat[p] = f(dat[p << 1], dat[p << 1 | 1]) dat[p] dat p f(dat[p << 1], dat[p << 1 | 1]) f dat[p << 1] dat p << 1 p 1 dat[p << 1 | 1] dat p << 1 | 1 p << 1 p 1 1 self self p p v v 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) query f, ti, n, dat = self.f, self.ti, self.n, self.dat f self.f self f ti self.ti self ti n self.n self n dat self.dat self dat vl = vr = ti vl ti = vr = ti vr ti l += n l n r += 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
         l < r l r if l & 1:
                vl = f(vl, dat[l])
                l += 1
             l & 1 l 1 vl = f(vl, dat[l]) vl f(vl, dat[l]) f vl dat[l] dat l l += 1 l 1 if r & 1:
                r -= 1
                vr = f(dat[r], vr)
             r & 1 r 1 r -= 1 r 1 vr = f(dat[r], vr) vr f(dat[r], vr) f dat[r] dat r vr l >>= 1 l 1 r >>= 1 r 1 return f(vl, vr) f(vl, vr) f vl vr self self l l r r ans = -10**20 ans -10**20 -10 20 se = set() se set() 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) start range(N) range N if start in se:
        continue
     start in se start se continue now = start now start scores = [] scores [] while True:
        if now in se:
            break
        se.add(now)
        scores += [C[now]]
        now = P[now]
     True if now in se:
            break
         now in se now se break se.add(now) se.add se add now scores += [C[now]] scores [C[now]] C[now] C now now = P[now] now P[now] P now cyclelen = len(scores) cyclelen len(scores) len scores cum = list(itertools.accumulate(scores * 3)) cum list(itertools.accumulate(scores * 3)) list itertools.accumulate(scores * 3) itertools.accumulate itertools accumulate scores * 3 scores 3 st = SegmentTree(cum, max, -10**20) st SegmentTree(cum, max, -10**20) SegmentTree cum max -10**20 -10 20 cycle, residue = divmod(K, cyclelen) cycle divmod(K, cyclelen) divmod K cyclelen residue st.query(start2 + 1, start2 + 1 + min(cyclelen, K)) - cum[start2]
        for start2 in range(cyclelen) for start2 in range(cyclelen) start2 range(cyclelen) range cyclelen for start2 in range(cyclelen) st.query(start2 + 1, start2 + 1 + min(cyclelen, K)) - cum[start2] st.query(start2 + 1, start2 + 1 + min(cyclelen, K)) st.query st query start2 + 1 start2 1 start2 + 1 + min(cyclelen, K) start2 + 1 start2 1 min(cyclelen, K) min cyclelen K cum[start2] cum start2 ans = max([ans] + [
        st.query(start2 + 1, start2 + 1 + min(cyclelen, K)) - cum[start2]
        for start2 in range(cyclelen)
    ]) ans max([ans] + [
        st.query(start2 + 1, start2 + 1 + min(cyclelen, K)) - cum[start2]
        for start2 in range(cyclelen)
    ]) max [ans] + [
        st.query(start2 + 1, start2 + 1 + min(cyclelen, K)) - cum[start2]
        for start2 in range(cyclelen)
    ] [ans] 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) cum[-1] > 0 and cycle > 0 cum[-1] > 0 cum[-1] cum -1 0 cycle > 0 cycle 0 v = cum[-1] * cycle // 3 + max(
            st.query(0, start2 + residue + 1) - cum[start2]
            for start2 in range(cyclelen, 2 * cyclelen)) v cum[-1] * cycle // 3 + max(
            st.query(0, start2 + residue + 1) - cum[start2]
            for start2 in range(cyclelen, 2 * cyclelen)) cum[-1] * cycle // 3 cum[-1] * cycle cum[-1] cum -1 cycle 3 max(
            st.query(0, start2 + residue + 1) - cum[start2]
            for start2 in range(cyclelen, 2 * cyclelen)) max st.query(0, start2 + residue + 1) - cum[start2] st.query(0, start2 + residue + 1) st.query st query 0 start2 + residue + 1 start2 + residue start2 residue 1 cum[start2] cum start2 ans = max(ans, v) ans max(ans, v) max ans v print(ans) print ans K = [int(_) for _ in input().split()] [int(_) for _ in input().split()] K cycle, residue = divmod(K, cyclelen) divmod(K, cyclelen) cycle cum = list(itertools.accumulate(scores * 3)) list(itertools.accumulate(scores * 3)) cum st = SegmentTree(cum, max, -10**20) SegmentTree(cum, max, -10**20) st scores = [] [] scores C = [int(_) for _ in input().split()] [int(_) for _ in input().split()] C now = start start now N, K = [int(_) for _ in input().split()] [int(_) for _ in input().split()] N residue = divmod(K, cyclelen) divmod(K, cyclelen) residue ans = max([ans] + [
        st.query(start2 + 1, start2 + 1 + min(cyclelen, K)) - cum[start2]
        for start2 in range(cyclelen)
    ]) max([ans] + [
        st.query(start2 + 1, start2 + 1 + min(cyclelen, K)) - cum[start2]
        for start2 in range(cyclelen)
    ]) ans P = [int(_) - 1 for _ in input().split()] [int(_) - 1 for _ in input().split()] P scores += [C[now]] [C[now]] scores ans = max(ans, v) max(ans, v) ans se = set() set() se v = cum[-1] * cycle // 3 + max(
            st.query(0, start2 + residue + 1) - cum[start2]
            for start2 in range(cyclelen, 2 * cyclelen)) cum[-1] * cycle // 3 + max(
            st.query(0, start2 + residue + 1) - cum[start2]
            for start2 in range(cyclelen, 2 * cyclelen)) v cyclelen = len(scores) len(scores) cyclelen ans = -10**20 -10**20 ans 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) 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) SegmentTree now = P[now] P[now] now
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)
