You are given a rooted tree on n vertices, its root is the vertex number 1. The i-th vertex contains a number w_i. Split it into the minimum possible number of vertical paths in such a way that each path contains no more than L vertices and the sum of integers w_i on each path does not exceed S. Each vertex should belong to exactly one path.

A vertical path is a sequence of vertices v_1, v_2, …, v_k where v_i (i ≥ 2) is the parent of v_{i - 1}.

Input

The first line contains three integers n, L, S (1 ≤ n ≤ 10^5, 1 ≤ L ≤ 10^5, 1 ≤ S ≤ 10^{18}) — the number of vertices, the maximum number of vertices in one path and the maximum sum in one path.

The second line contains n integers w_1, w_2, …, w_n (1 ≤ w_i ≤ 10^9) — the numbers in the vertices of the tree.

The third line contains n - 1 integers p_2, …, p_n (1 ≤ p_i < i), where p_i is the parent of the i-th vertex in the tree.

Output

Output one number — the minimum number of vertical paths. If it is impossible to split the tree, output -1.

Examples

Input

3 1 3
1 2 3
1 1


Output

3

Input

3 3 6
1 2 3
1 1


Output

2

Input

1 1 10000
10001


Output

-1

Note

In the first sample the tree is split into \{1\},\ \{2\},\ \{3\}.

In the second sample the tree is split into \{1,\ 2\},\ \{3\} or \{1,\ 3\},\ \{2\}.

In the third sample it is impossible to split the tree.
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayDeque;
import java.util.Arrays;

public class E {
/*
 * 
 * 
7 5 30
10 5 20 15 30 1 2
1 2 3 4 5 6
 */
	static int N;
	static int child[][];
	static int par[];
	static long L,S;
	static long w[];
	static long cumSum[];
	
	static int res;
	
	static int lift[][];
	static int dep[];
	static int maxLog[];
	
	static int curL[];
	static long curSum[];
	
	static final boolean debug = false;
	public static void main(String[] args) {
		JS in = new JS();
		//Can always give each node it's own thing
		N = in.nextInt();
		L = in.nextLong();
		S = in.nextLong();
		w = new long[N];
		boolean good = true;
		for(int i = 0; i < N; i++) {
			w[i] = in.nextLong();
			if(w[i] > S) good = false;
		}
		if(!good) {
			System.out.println(-1);
			return;
		}
		par = new int[N];
		int cnt[] = new int[N];
		par[0]=-1;
		for(int i = 1; i <= N-1; i++) {
			int p = in.nextInt()-1;
			par[i]=p;
			cnt[p]++;
		}
		child = new int[N][];
		for(int i = 0; i < N; i++) child[i] = new int[cnt[i]];
		for(int i = 1; i <= N-1; i++) {
			int p = par[i];
			child[p][--cnt[p]]=i;
		}
		
		
		//Make the binary lifting table
		//child[i] is an arraylist of i's children
		//par[i] is i's parent
		//root is the root of the tree
		int root = 0;
		lift = new int[N][];
		dep = new int[N];
		maxLog = new int[N];
		dep[root]=0;
		maxLog[root] = 2;
		lift[root] = new int[maxLog[0]];
		lift[root][0] = root;
		lift[root][1] = root;
		ArrayDeque<Integer> nodeQ = new ArrayDeque<Integer>();
		for(int next : child[root]) nodeQ.add(next);
		while(!nodeQ.isEmpty()) {
			int node = nodeQ.poll();
			dep[node]=dep[par[node]]+1;
			int log = 31 - Integer.numberOfLeadingZeros(dep[node])+2;
			maxLog[node] = log;
			lift[node] = new int[log+1];
			Arrays.fill(lift[node], root);
			lift[node][0] = par[node];

			int curNode = par[node];
			for(int i = 1;;i++) {
				if(i-1 >= maxLog[curNode]) curNode = root;
				else curNode = lift[curNode][i-1];
				lift[node][i] = curNode;
				if(curNode==root)break;
			}
			for(int next : child[node]) nodeQ.add(next);
		}
		
		cumSum = new long[N];
		initSum(0);
		
		curL = new int[N];
		curSum = new long[N];
		res = 0;
		solve(0);
		System.out.println(res);
	}
	static void initSum(int node) {
		//System.out.println("N="+node);
		cumSum[node]=w[node] + (par[node]==-1? 0 : cumSum[par[node]]);
		for(int ii : child[node])initSum(ii);
	}
	static void solve(int node) {
		if(child[node].length==0) {
			if(debug)System.out.println("Leaf: "+(node+1));
			res++;
			curL[node]=1;
			curSum[node]=w[node];
		}
		else {
			for(int ii : child[node]) solve(ii);
			int bestNode = -1;
			int bestLen = 0;
			long bestSum = 0;
			
			//get the node that can go farthest up (including us)
			if(debug)System.out.println("CurNode: "+(node+1));
			for(int ii : child[node]) {
				//do binary lifting to get the thingy
				int curNode = ii;
				long sum = curSum[ii];
				int len = curL[ii];
				if(debug)System.out.println("CH: "+ (ii+1)+"  l="+len+"  s="+sum);

				
				for(int bl = maxLog[curNode]; bl >= 0; bl--) {
					if(bl > maxLog[curNode])bl=maxLog[curNode]; //because of going up tree and index out of bounds
					
					int nextNode = lift[curNode][bl];
					int numAddedNodes = dep[curNode]-dep[nextNode];
					long addedSum = cumSum[par[curNode]]-(nextNode==0?0:cumSum[par[nextNode]]);
					int newLen = len+numAddedNodes;
					long newSum = sum+addedSum;
					if(newLen > L || newSum > S)continue; //doesn't work, onto next node
					else { //if it does work
						curNode = nextNode;
						sum = newSum;
						len = newLen;
						if(curNode==0)break; //if we hit root then nothing more to do
					}
				}
				//now we know how far it reaches, we need to see how much MORE it is
				int deltaLen = len-curL[ii];
				if(deltaLen > bestLen) {
					bestNode=ii;
					bestLen=deltaLen;
					bestSum=sum;
				}
				else if(deltaLen == bestLen && sum < bestSum) {
					bestNode=ii;
					bestLen=deltaLen;
					bestSum=sum;
				}		
			}
			if(debug)System.out.println("Bestnode: "+(bestNode+1));
			
			if(bestNode==-1) {
				res++;
				curL[node]=1;
				curSum[node]=w[node];
			}
			else {
				if(debug)System.out.println("  here: "+curL[bestNode]+"  "+curSum[bestNode]);
				curL[node]=curL[bestNode]+1;
				curSum[node]=curSum[bestNode]+w[node];
			}
		}
	}

	
	static class JS{
		public int BS = 1<<16;
		public char NC = (char)0;
		byte[] buf = new byte[BS];
		int bId = 0, size = 0;
		char c = NC;
		double num = 1;
		BufferedInputStream in;
		
		public JS() {
			in = new BufferedInputStream(System.in, BS);
		}
		
		public JS(String s) throws FileNotFoundException {
			in = new BufferedInputStream(new FileInputStream(new File(s)), BS);
		}
		
		public char nextChar(){
			while(bId==size) {
				try {
					size = in.read(buf);
				}catch(Exception e) {
					return NC;
				}				
				if(size==-1)return NC;
				bId=0;
			}
			return (char)buf[bId++];
		}
		
		public int nextInt() {
			return (int)nextLong();
		}
		
		public long nextLong() {
			num=1;
			boolean neg = false;
			if(c==NC)c=nextChar();
			for(;(c<'0' || c>'9'); c = nextChar()) {
				if(c=='-')neg=true;
			}
			long res = 0;
			for(; c>='0' && c <='9'; c=nextChar()) {
				res = (res<<3)+(res<<1)+c-'0';
				num*=10;
			}
			return neg?-res:res;
		}
		
		public double nextDouble() {
		    while(c!='.'&&c!='-'&&(c <'0' || c>'9')) c = nextChar();
		    boolean neg = c=='-';
		    if(neg)c=nextChar();
		    boolean fl = c=='.';
		    double cur = nextLong();
		    if(fl) return neg ? -cur/num : cur/num;
		    if(c == '.') {
			double next = nextLong();
			return neg ? -cur-next/num : cur+next/num;
		    }
		    else return neg ? -cur : cur;
		}
		
		public String next() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c>32) {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}
		
		public String nextLine() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c!='\n') {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public boolean hasNext() {
			if(c>32)return true;
			while(true) {
				c=nextChar();
				if(c==NC)return false;
				else if(c>32)return true;
			}
		}
	}
	
}
