#D
class UnionFind():
    # https://www.slideshare.net/chokudai/union-find-49066733
    # 作りたい要素数nで初期化
    # 使用するインスタンス変数の初期化
    def __init__(self, n):
        self.n = n
        # root[x]<0ならそのノードが根かつその値が木の要素数
        # rootノードでその木の要素数を記録する
        # root[x]>=0の場合は、特に直接的な意味を持たない気がする。計算に寄与するので意味はあるのだろうが。
        self.root = [-1]*(n+1)
        # 木をくっつける時にアンバランスにならないように調整する
        # 無結合の時はRank=0,結合して1つ木が深くなると根がRank+=1
        self.rnk = [0]*(n+1)

    # ノードxのrootノードを見つける
    #
    def Find_Root(self, x):
        if(self.root[x] < 0):
            return x
        else:
            # ここで代入しておくことで、後の繰り返しを避ける
            self.root[x] = self.Find_Root(self.root[x])
            return self.root[x]

    # 木の併合、入力は併合したい各ノード
    def Unite(self, x, y):
        # 入力ノードのrootノードを見つける
        x = self.Find_Root(x)
        y = self.Find_Root(y)
        # すでに同じ木に属していた場合
        if(x == y):
            return
        # 違う木に属していた場合rnkを見てくっつける方を決める
        # (1)xのランクの方が大きい(位置が深い)場合
        elif(self.rnk[x] > self.rnk[y]):
            self.root[x] += self.root[y]
            self.root[y] = x

        # (2)yのランクの方が大きい(位置が深い)場合 or 等しい場合
        # また等しい場合、引数の2つめのyの方のランクを1つ増やす
        else:
            self.root[y] += self.root[x]
            self.root[x] = y
            # rnkが同じ（深さに差がない場合）は1増やす
            if(self.rnk[x] == self.rnk[y]):
                self.rnk[y] += 1

    # xとyが同じグループに属するか判断
    # Return: True or False
    def isSameGroup(self, x, y):
        return self.Find_Root(x) == self.Find_Root(y)

    # ノードxが属する木のサイズを返す
    def Count(self, x):
        return -self.root[self.Find_Root(x)]
###################################################################    
N,K=map(int,input().split())
UN=UnionFind(N)
P=list(map(int,input().split()))
C=list(map(int,input().split()))
for i,num in enumerate(P):
    UN.Unite(i+1,num)
root=set()
loop_score=dict()
loop_len=dict()

#print(UN.root)
for i,node in enumerate(UN.root):
    if i==0:
        pass
    else:
        if node<0:
            #print(i,"is root")
            root.add(i)
            score=0
            ini=i
            leng=0
            while True:
                ret=P[ini-1]
                score += C[ret-1]
                leng +=1
                if ret==i:
                    break
                else:
                    ini=ret
            loop_score[i]=score
            loop_len[i] = leng
            
#print(loop_score)
#print(loop_len)

ans_list=[]
ans=float("-inf")

for i in range(1,N+1):
    t=K
    p=UN.Find_Root(i)
    
    
    #ループした方がいいかの確認
    if loop_score[p]>0:
        tmp=0
        pos=i
        tmp += ((t//loop_len[p])-1)*loop_score[p]
        if tmp>0:
            ans=max(tmp,ans)
        t = (t%loop_len[p])+loop_len[p]
        for j in range(t):
            pos = P[pos-1]
            tmp += C[pos-1]
            ans=max(tmp,ans)

    else:
        tmp=0
        pos=i
        
        for j in range(min(t,loop_len[p]-1)):
            pos = P[pos-1]
            tmp += C[pos-1]
            ans=max(tmp,ans)
    
print(ans) class UnionFind():
    # https://www.slideshare.net/chokudai/union-find-49066733
    # 作りたい要素数nで初期化
    # 使用するインスタンス変数の初期化
    def __init__(self, n):
        self.n = n
        # root[x]<0ならそのノードが根かつその値が木の要素数
        # rootノードでその木の要素数を記録する
        # root[x]>=0の場合は、特に直接的な意味を持たない気がする。計算に寄与するので意味はあるのだろうが。
        self.root = [-1]*(n+1)
        # 木をくっつける時にアンバランスにならないように調整する
        # 無結合の時はRank=0,結合して1つ木が深くなると根がRank+=1
        self.rnk = [0]*(n+1)

    # ノードxのrootノードを見つける
    #
    def Find_Root(self, x):
        if(self.root[x] < 0):
            return x
        else:
            # ここで代入しておくことで、後の繰り返しを避ける
            self.root[x] = self.Find_Root(self.root[x])
            return self.root[x]

    # 木の併合、入力は併合したい各ノード
    def Unite(self, x, y):
        # 入力ノードのrootノードを見つける
        x = self.Find_Root(x)
        y = self.Find_Root(y)
        # すでに同じ木に属していた場合
        if(x == y):
            return
        # 違う木に属していた場合rnkを見てくっつける方を決める
        # (1)xのランクの方が大きい(位置が深い)場合
        elif(self.rnk[x] > self.rnk[y]):
            self.root[x] += self.root[y]
            self.root[y] = x

        # (2)yのランクの方が大きい(位置が深い)場合 or 等しい場合
        # また等しい場合、引数の2つめのyの方のランクを1つ増やす
        else:
            self.root[y] += self.root[x]
            self.root[x] = y
            # rnkが同じ（深さに差がない場合）は1増やす
            if(self.rnk[x] == self.rnk[y]):
                self.rnk[y] += 1

    # xとyが同じグループに属するか判断
    # Return: True or False
    def isSameGroup(self, x, y):
        return self.Find_Root(x) == self.Find_Root(y)

    # ノードxが属する木のサイズを返す
    def Count(self, x):
        return -self.root[self.Find_Root(x)]
###################################################################     UnionFind def __init__(self, n):
        self.n = n
        # root[x]<0ならそのノードが根かつその値が木の要素数
        # rootノードでその木の要素数を記録する
        # root[x]>=0の場合は、特に直接的な意味を持たない気がする。計算に寄与するので意味はあるのだろうが。
        self.root = [-1]*(n+1)
        # 木をくっつける時にアンバランスにならないように調整する
        # 無結合の時はRank=0,結合して1つ木が深くなると根がRank+=1
        self.rnk = [0]*(n+1)

    # ノードxのrootノードを見つける
    #
     __init__ self.n = n self.n self n n self.root = [-1]*(n+1) self.root self root [-1]*(n+1) [-1] -1 n+1 n 1 self.rnk = [0]*(n+1) self.rnk self rnk [0]*(n+1) [0] 0 n+1 n 1 self self n n def Find_Root(self, x):
        if(self.root[x] < 0):
            return x
        else:
            # ここで代入しておくことで、後の繰り返しを避ける
            self.root[x] = self.Find_Root(self.root[x])
            return self.root[x]

    # 木の併合、入力は併合したい各ノード
     Find_Root if(self.root[x] < 0):
            return x
        else:
            # ここで代入しておくことで、後の繰り返しを避ける
            self.root[x] = self.Find_Root(self.root[x])
            return self.root[x]

    # 木の併合、入力は併合したい各ノード
     self.root[x] < 0 self.root[x] self.root self root x 0 return x x self.root[x] = self.Find_Root(self.root[x]) self.root[x] self.root self root x self.Find_Root(self.root[x]) self.Find_Root self Find_Root self.root[x] self.root self root x return self.root[x] self.root[x] self.root self root x self self x x def Unite(self, x, y):
        # 入力ノードのrootノードを見つける
        x = self.Find_Root(x)
        y = self.Find_Root(y)
        # すでに同じ木に属していた場合
        if(x == y):
            return
        # 違う木に属していた場合rnkを見てくっつける方を決める
        # (1)xのランクの方が大きい(位置が深い)場合
        elif(self.rnk[x] > self.rnk[y]):
            self.root[x] += self.root[y]
            self.root[y] = x

        # (2)yのランクの方が大きい(位置が深い)場合 or 等しい場合
        # また等しい場合、引数の2つめのyの方のランクを1つ増やす
        else:
            self.root[y] += self.root[x]
            self.root[x] = y
            # rnkが同じ（深さに差がない場合）は1増やす
            if(self.rnk[x] == self.rnk[y]):
                self.rnk[y] += 1

    # xとyが同じグループに属するか判断
    # Return: True or False
     Unite x = self.Find_Root(x) x self.Find_Root(x) self.Find_Root self Find_Root x y = self.Find_Root(y) y self.Find_Root(y) self.Find_Root self Find_Root y if(x == y):
            return
        # 違う木に属していた場合rnkを見てくっつける方を決める
        # (1)xのランクの方が大きい(位置が深い)場合
        elif(self.rnk[x] > self.rnk[y]):
            self.root[x] += self.root[y]
            self.root[y] = x

        # (2)yのランクの方が大きい(位置が深い)場合 or 等しい場合
        # また等しい場合、引数の2つめのyの方のランクを1つ増やす
        else:
            self.root[y] += self.root[x]
            self.root[x] = y
            # rnkが同じ（深さに差がない場合）は1増やす
            if(self.rnk[x] == self.rnk[y]):
                self.rnk[y] += 1

    # xとyが同じグループに属するか判断
    # Return: True or False
     x == y x y return elif(self.rnk[x] > self.rnk[y]):
            self.root[x] += self.root[y]
            self.root[y] = x

        # (2)yのランクの方が大きい(位置が深い)場合 or 等しい場合
        # また等しい場合、引数の2つめのyの方のランクを1つ増やす
         self.rnk[x] > self.rnk[y] self.rnk[x] self.rnk self rnk x self.rnk[y] self.rnk self rnk y self.root[x] += self.root[y] self.root[x] self.root self root x self.root[y] self.root self root y self.root[y] = x self.root[y] self.root self root y x self.root[y] += self.root[x] self.root[y] self.root self root y self.root[x] self.root self root x self.root[x] = y self.root[x] self.root self root x y if(self.rnk[x] == self.rnk[y]):
                self.rnk[y] += 1

    # xとyが同じグループに属するか判断
    # Return: True or False
     self.rnk[x] == self.rnk[y] self.rnk[x] self.rnk self rnk x self.rnk[y] self.rnk self rnk y self.rnk[y] += 1 self.rnk[y] self.rnk self rnk y 1 self self x x y y def isSameGroup(self, x, y):
        return self.Find_Root(x) == self.Find_Root(y)

    # ノードxが属する木のサイズを返す
     isSameGroup return self.Find_Root(x) == self.Find_Root(y) self.Find_Root(x) == self.Find_Root(y) self.Find_Root(x) self.Find_Root self Find_Root x self.Find_Root(y) self.Find_Root self Find_Root y self self x x y y def Count(self, x):
        return -self.root[self.Find_Root(x)]
###################################################################     Count return -self.root[self.Find_Root(x)] -self.root[self.Find_Root(x)] self.root[self.Find_Root(x)] self.root self root self.Find_Root(x) self.Find_Root self Find_Root x self self x x N,K=map(int,input().split()) N map(int,input().split()) map int input().split() ().split () input split K UN=UnionFind(N) UN UnionFind(N) UnionFind N P=list(map(int,input().split())) P list(map(int,input().split())) list map(int,input().split()) map int input().split() ().split () input split C=list(map(int,input().split())) C list(map(int,input().split())) list map(int,input().split()) map int input().split() ().split () input split for i,num in enumerate(P):
    UN.Unite(i+1,num) i num enumerate(P) enumerate P UN.Unite(i+1,num) UN.Unite UN Unite i+1 i 1 num root=set() root set() set loop_score=dict() loop_score dict() dict loop_len=dict() loop_len dict() dict for i,node in enumerate(UN.root):
    if i==0:
        pass
    else:
        if node<0:
            #print(i,"is root")
            root.add(i)
            score=0
            ini=i
            leng=0
            while True:
                ret=P[ini-1]
                score += C[ret-1]
                leng +=1
                if ret==i:
                    break
                else:
                    ini=ret
            loop_score[i]=score
            loop_len[i] = leng
            
#print(loop_score)
#print(loop_len) i node enumerate(UN.root) enumerate UN.root UN root if i==0:
        pass
    else:
        if node<0:
            #print(i,"is root")
            root.add(i)
            score=0
            ini=i
            leng=0
            while True:
                ret=P[ini-1]
                score += C[ret-1]
                leng +=1
                if ret==i:
                    break
                else:
                    ini=ret
            loop_score[i]=score
            loop_len[i] = leng
            
#print(loop_score)
#print(loop_len) i==0 i 0 if node<0:
            #print(i,"is root")
            root.add(i)
            score=0
            ini=i
            leng=0
            while True:
                ret=P[ini-1]
                score += C[ret-1]
                leng +=1
                if ret==i:
                    break
                else:
                    ini=ret
            loop_score[i]=score
            loop_len[i] = leng
            
#print(loop_score)
#print(loop_len) node<0 node 0 root.add(i) root.add root add i score=0 score 0 ini=i ini i leng=0 leng 0 while True:
                ret=P[ini-1]
                score += C[ret-1]
                leng +=1
                if ret==i:
                    break
                else:
                    ini=ret
             True ret=P[ini-1] ret P[ini-1] P ini-1 ini 1 score += C[ret-1] score C[ret-1] C ret-1 ret 1 leng +=1 leng 1 if ret==i:
                    break
                else:
                    ini=ret
             ret==i ret i break ini=ret ini ret loop_score[i]=score loop_score[i] loop_score i score loop_len[i] = leng loop_len[i] loop_len i leng ans_list=[] ans_list [] ans=float("-inf") ans float("-inf") float "-inf" for i in range(1,N+1):
    t=K
    p=UN.Find_Root(i)
    
    
    #ループした方がいいかの確認
    if loop_score[p]>0:
        tmp=0
        pos=i
        tmp += ((t//loop_len[p])-1)*loop_score[p]
        if tmp>0:
            ans=max(tmp,ans)
        t = (t%loop_len[p])+loop_len[p]
        for j in range(t):
            pos = P[pos-1]
            tmp += C[pos-1]
            ans=max(tmp,ans)

    else:
        tmp=0
        pos=i
        
        for j in range(min(t,loop_len[p]-1)):
            pos = P[pos-1]
            tmp += C[pos-1]
            ans=max(tmp,ans)
     i range(1,N+1) range 1 N+1 N 1 t=K t K p=UN.Find_Root(i) p UN.Find_Root(i) UN.Find_Root UN Find_Root i if loop_score[p]>0:
        tmp=0
        pos=i
        tmp += ((t//loop_len[p])-1)*loop_score[p]
        if tmp>0:
            ans=max(tmp,ans)
        t = (t%loop_len[p])+loop_len[p]
        for j in range(t):
            pos = P[pos-1]
            tmp += C[pos-1]
            ans=max(tmp,ans)

    else:
        tmp=0
        pos=i
        
        for j in range(min(t,loop_len[p]-1)):
            pos = P[pos-1]
            tmp += C[pos-1]
            ans=max(tmp,ans)
     loop_score[p]>0 loop_score[p] loop_score p 0 tmp=0 tmp 0 pos=i pos i tmp += ((t//loop_len[p])-1)*loop_score[p] tmp ((t//loop_len[p])-1)*loop_score[p] (t//loop_len[p])-1 t//loop_len[p] t loop_len[p] loop_len p 1 loop_score[p] loop_score p if tmp>0:
            ans=max(tmp,ans)
         tmp>0 tmp 0 ans=max(tmp,ans) ans max(tmp,ans) max tmp ans t = (t%loop_len[p])+loop_len[p] t (t%loop_len[p])+loop_len[p] t%loop_len[p] t loop_len[p] loop_len p loop_len[p] loop_len p for j in range(t):
            pos = P[pos-1]
            tmp += C[pos-1]
            ans=max(tmp,ans)

     j range(t) range t pos = P[pos-1] pos P[pos-1] P pos-1 pos 1 tmp += C[pos-1] tmp C[pos-1] C pos-1 pos 1 ans=max(tmp,ans) ans max(tmp,ans) max tmp ans tmp=0 tmp 0 pos=i pos i for j in range(min(t,loop_len[p]-1)):
            pos = P[pos-1]
            tmp += C[pos-1]
            ans=max(tmp,ans)
     j range(min(t,loop_len[p]-1)) range min(t,loop_len[p]-1) min t loop_len[p]-1 loop_len[p] loop_len p 1 pos = P[pos-1] pos P[pos-1] P pos-1 pos 1 tmp += C[pos-1] tmp C[pos-1] C pos-1 pos 1 ans=max(tmp,ans) ans max(tmp,ans) max tmp ans print(ans) print ans pos=i i pos N,K=map(int,input().split()) map(int,input().split()) N pos = P[pos-1] P[pos-1] pos tmp += ((t//loop_len[p])-1)*loop_score[p] ((t//loop_len[p])-1)*loop_score[p] tmp UN=UnionFind(N) UnionFind(N) UN class UnionFind():
    # https://www.slideshare.net/chokudai/union-find-49066733
    # 作りたい要素数nで初期化
    # 使用するインスタンス変数の初期化
    def __init__(self, n):
        self.n = n
        # root[x]<0ならそのノードが根かつその値が木の要素数
        # rootノードでその木の要素数を記録する
        # root[x]>=0の場合は、特に直接的な意味を持たない気がする。計算に寄与するので意味はあるのだろうが。
        self.root = [-1]*(n+1)
        # 木をくっつける時にアンバランスにならないように調整する
        # 無結合の時はRank=0,結合して1つ木が深くなると根がRank+=1
        self.rnk = [0]*(n+1)

    # ノードxのrootノードを見つける
    #
    def Find_Root(self, x):
        if(self.root[x] < 0):
            return x
        else:
            # ここで代入しておくことで、後の繰り返しを避ける
            self.root[x] = self.Find_Root(self.root[x])
            return self.root[x]

    # 木の併合、入力は併合したい各ノード
    def Unite(self, x, y):
        # 入力ノードのrootノードを見つける
        x = self.Find_Root(x)
        y = self.Find_Root(y)
        # すでに同じ木に属していた場合
        if(x == y):
            return
        # 違う木に属していた場合rnkを見てくっつける方を決める
        # (1)xのランクの方が大きい(位置が深い)場合
        elif(self.rnk[x] > self.rnk[y]):
            self.root[x] += self.root[y]
            self.root[y] = x

        # (2)yのランクの方が大きい(位置が深い)場合 or 等しい場合
        # また等しい場合、引数の2つめのyの方のランクを1つ増やす
        else:
            self.root[y] += self.root[x]
            self.root[x] = y
            # rnkが同じ（深さに差がない場合）は1増やす
            if(self.rnk[x] == self.rnk[y]):
                self.rnk[y] += 1

    # xとyが同じグループに属するか判断
    # Return: True or False
    def isSameGroup(self, x, y):
        return self.Find_Root(x) == self.Find_Root(y)

    # ノードxが属する木のサイズを返す
    def Count(self, x):
        return -self.root[self.Find_Root(x)]
###################################################################     class UnionFind():
    # https://www.slideshare.net/chokudai/union-find-49066733
    # 作りたい要素数nで初期化
    # 使用するインスタンス変数の初期化
    def __init__(self, n):
        self.n = n
        # root[x]<0ならそのノードが根かつその値が木の要素数
        # rootノードでその木の要素数を記録する
        # root[x]>=0の場合は、特に直接的な意味を持たない気がする。計算に寄与するので意味はあるのだろうが。
        self.root = [-1]*(n+1)
        # 木をくっつける時にアンバランスにならないように調整する
        # 無結合の時はRank=0,結合して1つ木が深くなると根がRank+=1
        self.rnk = [0]*(n+1)

    # ノードxのrootノードを見つける
    #
    def Find_Root(self, x):
        if(self.root[x] < 0):
            return x
        else:
            # ここで代入しておくことで、後の繰り返しを避ける
            self.root[x] = self.Find_Root(self.root[x])
            return self.root[x]

    # 木の併合、入力は併合したい各ノード
    def Unite(self, x, y):
        # 入力ノードのrootノードを見つける
        x = self.Find_Root(x)
        y = self.Find_Root(y)
        # すでに同じ木に属していた場合
        if(x == y):
            return
        # 違う木に属していた場合rnkを見てくっつける方を決める
        # (1)xのランクの方が大きい(位置が深い)場合
        elif(self.rnk[x] > self.rnk[y]):
            self.root[x] += self.root[y]
            self.root[y] = x

        # (2)yのランクの方が大きい(位置が深い)場合 or 等しい場合
        # また等しい場合、引数の2つめのyの方のランクを1つ増やす
        else:
            self.root[y] += self.root[x]
            self.root[x] = y
            # rnkが同じ（深さに差がない場合）は1増やす
            if(self.rnk[x] == self.rnk[y]):
                self.rnk[y] += 1

    # xとyが同じグループに属するか判断
    # Return: True or False
    def isSameGroup(self, x, y):
        return self.Find_Root(x) == self.Find_Root(y)

    # ノードxが属する木のサイズを返す
    def Count(self, x):
        return -self.root[self.Find_Root(x)]
###################################################################     UnionFind pos = P[pos-1] P[pos-1] pos tmp=0 0 tmp tmp=0 0 tmp score=0 0 score tmp += C[pos-1] C[pos-1] tmp ans_list=[] [] ans_list ans=max(tmp,ans) max(tmp,ans) ans C=list(map(int,input().split())) list(map(int,input().split())) C ans=float("-inf") float("-inf") ans p=UN.Find_Root(i) UN.Find_Root(i) p ini=ret ret ini pos=i i pos ret=P[ini-1] P[ini-1] ret loop_len=dict() dict() loop_len score += C[ret-1] C[ret-1] score leng=0 0 leng tmp += C[pos-1] C[pos-1] tmp t=K K t t = (t%loop_len[p])+loop_len[p] (t%loop_len[p])+loop_len[p] t ini=i i ini root=set() set() root ans=max(tmp,ans) max(tmp,ans) ans K=map(int,input().split()) map(int,input().split()) K P=list(map(int,input().split())) list(map(int,input().split())) P loop_score=dict() dict() loop_score ans=max(tmp,ans) max(tmp,ans) ans leng +=1 1 leng
#D
class UnionFind():
    # https://www.slideshare.net/chokudai/union-find-49066733
    # 作りたい要素数nで初期化
    # 使用するインスタンス変数の初期化
    def __init__(self, n):
        self.n = n
        # root[x]<0ならそのノードが根かつその値が木の要素数
        # rootノードでその木の要素数を記録する
        # root[x]>=0の場合は、特に直接的な意味を持たない気がする。計算に寄与するので意味はあるのだろうが。
        self.root = [-1]*(n+1)
        # 木をくっつける時にアンバランスにならないように調整する
        # 無結合の時はRank=0,結合して1つ木が深くなると根がRank+=1
        self.rnk = [0]*(n+1)

    # ノードxのrootノードを見つける
    #
    def Find_Root(self, x):
        if(self.root[x] < 0):
            return x
        else:
            # ここで代入しておくことで、後の繰り返しを避ける
            self.root[x] = self.Find_Root(self.root[x])
            return self.root[x]

    # 木の併合、入力は併合したい各ノード
    def Unite(self, x, y):
        # 入力ノードのrootノードを見つける
        x = self.Find_Root(x)
        y = self.Find_Root(y)
        # すでに同じ木に属していた場合
        if(x == y):
            return
        # 違う木に属していた場合rnkを見てくっつける方を決める
        # (1)xのランクの方が大きい(位置が深い)場合
        elif(self.rnk[x] > self.rnk[y]):
            self.root[x] += self.root[y]
            self.root[y] = x

        # (2)yのランクの方が大きい(位置が深い)場合 or 等しい場合
        # また等しい場合、引数の2つめのyの方のランクを1つ増やす
        else:
            self.root[y] += self.root[x]
            self.root[x] = y
            # rnkが同じ（深さに差がない場合）は1増やす
            if(self.rnk[x] == self.rnk[y]):
                self.rnk[y] += 1

    # xとyが同じグループに属するか判断
    # Return: True or False
    def isSameGroup(self, x, y):
        return self.Find_Root(x) == self.Find_Root(y)

    # ノードxが属する木のサイズを返す
    def Count(self, x):
        return -self.root[self.Find_Root(x)]
###################################################################    
N,K=map(int,input().split())
UN=UnionFind(N)
P=list(map(int,input().split()))
C=list(map(int,input().split()))
for i,num in enumerate(P):
    UN.Unite(i+1,num)
root=set()
loop_score=dict()
loop_len=dict()

#print(UN.root)
for i,node in enumerate(UN.root):
    if i==0:
        pass
    else:
        if node<0:
            #print(i,"is root")
            root.add(i)
            score=0
            ini=i
            leng=0
            while True:
                ret=P[ini-1]
                score += C[ret-1]
                leng +=1
                if ret==i:
                    break
                else:
                    ini=ret
            loop_score[i]=score
            loop_len[i] = leng
            
#print(loop_score)
#print(loop_len)

ans_list=[]
ans=float("-inf")

for i in range(1,N+1):
    t=K
    p=UN.Find_Root(i)
    
    
    #ループした方がいいかの確認
    if loop_score[p]>0:
        tmp=0
        pos=i
        tmp += ((t//loop_len[p])-1)*loop_score[p]
        if tmp>0:
            ans=max(tmp,ans)
        t = (t%loop_len[p])+loop_len[p]
        for j in range(t):
            pos = P[pos-1]
            tmp += C[pos-1]
            ans=max(tmp,ans)

    else:
        tmp=0
        pos=i
        
        for j in range(min(t,loop_len[p]-1)):
            pos = P[pos-1]
            tmp += C[pos-1]
            ans=max(tmp,ans)
    
print(ans)