// Original C++ solution (slower):
#include <bits/stdc++.h>



using namespace std;



#define pb push_back

#define mem(a) memset(a,0,sizeof(a))



typedef long long ll;

typedef pair<int,int> pii;



const int mn=55;



int n;

ll m,D;

int a[mn];

vector<int> g[mn];

struct item{

	ll v,w,num;//value weight

	bool operator < (const item &e) const{

		return v*e.w>e.v*w;

	}

}p[mn];

void dfs(int v,int x){

	p[x].w+=a[v];

	p[x].v++;

	for(int &i:g[v]){

		dfs(i,x);

	}

}



ll d[mn*mn*mn];



inline ll greedy(ll m){

	ll ans=0;

	for (int i = 1; i <= n; i++) {

		ll u = min(m / p[i].w,p[i].num);

		m -= u * p[i].w, ans += p[i].v * u;

	}

	return ans;

}



int main() {

	ios::sync_with_stdio(0);

	cin >> n >> m >> D;

	cin >> a[1];

	for (int i = 2; i <= n; i++) {

		int u;

		cin >> a[i] >> u;

		g[u].pb(i);

		p[i].num = max(D - 50,0ll);

	}

	p[1].num = 1e9;

	for (int i = 1; i <= n; i++) dfs(i, i);

	sort(p + 1, p + n + 1);

	int maxpos = 0;

	fill_n(d, mn*mn*mn, 1ll << 58);

	d[0] = 0;

	for (int i = 1; i <= n; i++) {

		for (int k = 1; k <= min(50ll, D); k++) {

			maxpos += p[i].v;

			for (int j = maxpos; j >= p[i].v; j--) {

				d[j] = min(d[j], d[j - p[i].v] + p[i].w);

			}

		}

	}

	ll ans=0;

	for (int i = 0; i <= maxpos; i++) {

		if (d[i] <= m) ans=max(ans,greedy(m-d[i])+i);

	}

	cout << ans;

	return 0;

}

// Optimized solution to the same problem (faster):
#include <iostream> 

#include <cstdio> 

#include <cstdlib> 

#include <cstring> 

#include <cmath> 

#include <algorithm> 

using namespace std; 

typedef long long LL; 

const LL INF = 1e16; 

const int MAX_N = 55; 

const int MAX_V = 2e5 + 5; 

struct Graph { int to, next; } e[MAX_N << 1]; 

int fir[MAX_N], e_cnt; 

void clearGraph() { memset(fir, -1, sizeof(fir)); e_cnt = 0; } 

void Add_Edge(int u, int v) { e[e_cnt] = (Graph){v, fir[u]}, fir[u] = e_cnt++; } 



struct node { LL val, wei; bool op; } a[MAX_N]; 

bool operator < (const node &l, const node &r) 

    { return 1ll * l.val * r.wei > 1ll * l.wei * r.val; } 

int N, X, D; 

void dfs(int x) { 

	for (int i = fir[x]; ~i; i = e[i].next) { 

		int v = e[i].to; 

		dfs(v); 

		a[x].val += a[v].val; 

		a[x].wei += a[v].wei; 

	} 

} 

int V, lim;

LL f[MAX_V]; 

void ins(LL w, LL v) { 

	for (int i = V; i >= v; i--) 

        f[i] = min(f[i], f[i - v] + w); 

} 

void add(node p) { 

	int t = lim; 

	for (int i = 0; 1 << i <= t; i++) 

		ins(p.wei * (1 << i), p.val * (1 << i)), t -= 1 << i; 

	if (t) ins(p.wei * t, p.val * t); 

} 

int main () { 

	clearGraph(); 

	scanf("%d %d %d", &N, &X, &D); 

	scanf("%lld", &a[1].wei), a[1].val = 1, a[1].op = 1; 

	for (int i = 2; i <= N; i++) { 

		int w, fa; scanf("%d %d", &w, &fa); 

		a[i].wei = w, a[i].val = 1, Add_Edge(fa, i); 

	} 

	dfs(1); 

	lim = min(N, D); 

	V = N * N * N; 

	for (int i = 0; i <= V; i++) f[i] = INF; 

	f[0] = 0; 

	for (int i = 1; i <= N; i++) add(a[i]); 

	sort(&a[1], &a[N + 1]); 

	while (!a[N].op) --N; 

	LL ans = 0; 

	for (int i = 0; i <= V; i++) { 

		if (f[i] > X) continue; 

		LL val = i, wei = f[i]; 

		for (int j = 1; j < N; j++) { 

			LL cnt = min(1ll * D - lim, (X - wei) / a[j].wei); 

			val += cnt * a[j].val, wei += cnt * a[j].wei; 

		} 

		LL cnt = (X - wei) / a[N].wei; 

		ans = max(ans, val + cnt * a[N].val); 

	} 

	printf("%lld\n", ans); 

    return 0; 

} 

// Fastest known solution for this problem: