#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map>
#include <stack>
#include <sstream>
#include <set>
// #pragma GCC optimize(2)

//#define int long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define rush() int T;scanf("%d",&T);for(int Ti=1;Ti<=T;++Ti)
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define mm(i,v) memset(i,v,sizeof i);
#define mp(a, b) make_pair(a, b)
#define pi acos(-1)
#define fi first
#define se second
//你冷静一点，确认思路再敲！！！

using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int, int > PII;
priority_queue< PII, vector<PII>, greater<PII> > que;
stringstream ssin; //  ssin << string   while ( ssin >> int)
const ll LINF = 0x7fffffffffffffffll;

const ll N = 2e5 + 5, M = 4e5 + 5, mod = 1e9 + 7, INF = 0x3f3f3f3f;
ll _, n, s, idx;
ll e[M], ne[M], h[N], w1[M], w2[M];
ll leaf[N];
vector<ll>vec[3];
ll arr[3][N*21];
int cnt1, cnt2;

inline ll read() {
    char c=getchar();ll x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    return x*f;
}

void init() {
    cnt1 = cnt2 = idx = 0;
    for (int i = 1; i < min(N, n + n); ++i) {
        h[i] = -1;
        leaf[i] = 0;
    }
    vec[1].clear();
    vec[2].clear();
}

struct node {
    ll u, v, w, c, num;
    double res;
    bool operator<(const node &x)const {
        return res < x.res;
    }
}E[M];

void add(ll a, ll b, ll w, ll c) {
    e[idx] = b;
    w1[idx] = w;
    w2[idx] = c;
    ne[idx] = h[a];
    h[a] = idx++;
}

void dfs(ll u, ll fa) {
    ll cnt = 0, ans = 0;
    for (int i = h[u]; ~i; i = ne[i]) {
        int v = e[i];
        if (v == fa) continue;
        dfs(v, u);
        cnt++;
        ans += leaf[v];
    }
    if (!cnt) leaf[u] = 1;
    else leaf[u] = ans;
}

bool cmp(ll x, ll y) {
    return x > y;
}

int main()
{
    // freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);
    _ = read();
    while (_--) {
        n = read(); s = read();
        init();
        for (int i = 1; i < n; ++i) {
            ll u, v, w, c;
            u = read(); v = read(); w = read(); c = read();
            E[i] = {u, v, w, c};
            add(u, v, w, c);
            add(v, u, w, c);
        }
        dfs(1, -1);
        ll nn = 0;
        for (int i = 1; i < n; ++i) {
            int a = E[i].u, b = E[i].v;
            E[i].num = min(leaf[a], leaf[b]);
            nn += E[i].num * E[i].w;
            ll now = E[i].w;
            int tmp = E[i].c;
            ll qq = E[i].num;
            while (now) {
                 //printf("now = %d push = %d\n", now, (now - now / 2) * qq);
                vec[tmp].push_back((now - now / 2) * qq);
                now /= 2;
            }
        }

        sort(vec[1].begin(), vec[1].end(), cmp);
        sort(vec[2].begin(), vec[2].end(), cmp);

        //for (int i = 0; i < vec[1].size(); ++i)
            //cout << vec[1][i] << '\n';

        for (int i = 0; i < vec[1].size(); ++i)
            arr[1][cnt1 + 1] = arr[1][cnt1] + vec[1][i], cnt1++;

        for (int i = 0; i < vec[2].size(); ++i)
            arr[2][cnt2 + 1] = arr[2][cnt2] + vec[2][i], cnt2++;

        ll ans = 0, Min = 1e18;
        s = nn - s;
        if (cnt2 == 0)
            Min = lower_bound(arr[1], arr[1] + cnt1 + 1, s) - arr[1];
        else
        for (int i = 0; i <= cnt1; ++i) {
            ll tmp = s - arr[1][i];
            if (arr[2][cnt2] < tmp)
                continue;
            ans = i;
            int pos = lower_bound(arr[2], arr[2] + 1 + cnt2, tmp) - arr[2];
            ans += pos * 2;
            Min = min(Min, ans);
        }
        cout << Min << '\n';
    }
    #ifndef ONLINE_JUDGE
        system("pause");
    #endif
}

/*
2
10 28
8 2 8 1
5 1 4 1
6 1 10 1
10 2 7 1
7 2 1 1
9 2 1 1
2 1 5 1
4 1 9 1
3 2 5 1

7
*/


#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map>
#include <stack>
#include <sstream>
#include <set>
// #pragma GCC optimize(2)

//#define int long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define rush() int T;scanf("%d",&T);for(int Ti=1;Ti<=T;++Ti)
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define mm(i,v) memset(i,v,sizeof i);
#define mp(a, b) make_pair(a, b)
#define pi acos(-1)
#define fi first
#define se second
//你冷静一点，确认思路再敲！！！

using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int, int > PII;
priority_queue< PII, vector<PII>, greater<PII> > que;
stringstream ssin; //  ssin << string   while ( ssin >> int)
const ll LINF = 0x7fffffffffffffffll;

const ll N = 4e5 + 5, M = 4e5 + 5, mod = 1e9 + 7, INF = 0x3f3f3f3f;
ll _, n, s, idx;
ll e[M], ne[M], h[N], w1[M], w2[M];
ll leaf[N];

inline ll read() {
    char c=getchar();ll x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    return x*f;
}

void init() {
    idx = 0;
    for (int i = 1; i < min(N, n + n); ++i) h[i] = -1;
}

struct node {
    int u, v, w, c, num;
    double res;
    bool operator<(const node &x)const {
        return res < x.res;
    }
}E[M];

void add(ll a, ll b, ll w, ll c) {
    e[idx] = b;
    w1[idx] = w;
    w2[idx] = c;
    ne[idx] = h[a];
    h[a] = idx++;
}

void dfs(ll u, ll fa) {
    ll cnt = 0, ans = 0;
    for (int i = h[u]; ~i; i = ne[i]) {
        int v = e[i];
        if (v == fa) continue;
        dfs(v, u);
        cnt++;
        ans += leaf[v];
    }
    if (!cnt) leaf[u] = 1;
    else leaf[u] = ans;
}

int main()
{
    // freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);
    _ = read();
    while (_--) {
        n = read(); s = read();
        init();
        for (int i = 1; i < n; ++i) {
            ll u, v, w, c;
            u = read(); v = read(); w = read(); c = read();
            E[i] = {u, v, w, c};
            add(u, v, w, c);
            add(v, u, w, c);
        }
        dfs(1, -1);
        ll now = 0;
        priority_queue<node>q;
        for (int i = 1; i < n; ++i) {
            int a = E[i].u, b = E[i].v;
            E[i].num = min(leaf[a], leaf[b]);
            now += E[i].num * E[i].w;
            E[i].res = 1.0 * (E[i].w - E[i].w / 2) * E[i].num / E[i].c;
            q.push(E[i]);
        }

        // while (!q.empty()) {
        //     node t = q.top();
        //     q.pop();
        //     printf("%d %d %d %d %d %lf\n", t.u, t.v, t.w, t.c, t.num, t.res);
        // }

        // continue;

        ll ans = 0;
        // cout << now << '\n';
        while (now > s) {
            node tt, t;
            t = q.top();
            // printf("%d %d %d %d %d %lf\n", t.u, t.v, t.w, t.c, t.num, t.res);
            tt = t;
            q.pop();
            ans += t.c;
            now -= t.num * (t.w - t.w / 2);
            tt.w = t.w - t.w / 2;
            tt.res = 1.0 * (tt.w - tt.w / 2) * tt.num / tt.c;
            q.push(tt);
        }
        // cout << now << '\n';
        cout << ans << '\n';
    }
    #ifndef ONLINE_JUDGE
        system("pause");
    #endif
}


#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map>
#include <stack>
#include <sstream>
#include <set>
// #pragma GCC optimize(2)

//#define int long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define rush() int T;scanf("%d",&T);for(int Ti=1;Ti<=T;++Ti)
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define mm(i,v) memset(i,v,sizeof i);
#define mp(a, b) make_pair(a, b)
#define pi acos(-1)
#define fi first
#define se second
//你冷静一点，确认思路再敲！！！

using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int, int > PII;
priority_queue< PII, vector<PII>, greater<PII> > que;
stringstream ssin; //  ssin << string   while ( ssin >> int)
const ll LINF = 0x7fffffffffffffffll;

const ll N = 4e5 + 5, M = 4e5 + 5, mod = 1e9 + 7, INF = 0x3f3f3f3f;
ll _, n, s, idx;
ll e[M], ne[M], h[N], w1[M], w2[M];
ll leaf[N];
vector<ll>vec[3];
ll arr[3][N];
int cnt1, cnt2;

inline ll read() {
    char c=getchar();ll x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    return x*f;
}

void init() {
    cnt1 = cnt2 = idx = 0;
    for (int i = 1; i < min(N, n + n); ++i) {
        h[i] = -1;
        leaf[i] = 0;
    }
    vec[1].clear();
    vec[2].clear();
}

struct node {
    int u, v, w, c, num;
    double res;
    bool operator<(const node &x)const {
        return res < x.res;
    }
}E[M];

void add(ll a, ll b, ll w, ll c) {
    e[idx] = b;
    w1[idx] = w;
    w2[idx] = c;
    ne[idx] = h[a];
    h[a] = idx++;
}

void dfs(ll u, ll fa) {
    ll cnt = 0, ans = 0;
    for (int i = h[u]; ~i; i = ne[i]) {
        int v = e[i];
        if (v == fa) continue;
        dfs(v, u);
        cnt++;
        ans += leaf[v];
    }
    if (!cnt) leaf[u] = 1;
    else leaf[u] = ans;
}

bool cmp(int x, int y) {
    return x > y;
}

int main()
{
    // freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);
    _ = read();
    while (_--) {
        n = read(); s = read();
        init();
        for (int i = 1; i < n; ++i) {
            ll u, v, w, c;
            u = read(); v = read(); w = read(); c = read();
            E[i] = {u, v, w, c};
            add(u, v, w, c);
            add(v, u, w, c);
        }
        dfs(1, -1);
        ll nn = 0;
        for (int i = 1; i < n; ++i) {
            int a = E[i].u, b = E[i].v;
            E[i].num = min(leaf[a], leaf[b]);
            nn += E[i].num * E[i].w;
            ll now = E[i].w;
            int tmp = E[i].c;
            ll qq = E[i].num;
            while (now) {
                vec[tmp].push_back((now - now / 2) * qq);
                now /= 2;
            }
        }

        sort(vec[1].begin(), vec[1].end(), cmp);
        sort(vec[2].begin(), vec[2].end(), cmp);

        for (int i = 0; i < vec[1].size(); ++i)
            arr[1][cnt1 + 1] = arr[1][cnt1] + vec[1][i], cnt1++;

        for (int i = 0; i < vec[2].size(); ++i)
            arr[2][cnt2 + 1] = arr[2][cnt2] + vec[2][i], cnt2++;

        // for (int i = 0; i <= cnt1; ++i)
        //     cout << arr[1][i] << "-----1\n";
        // cout << "-----\n";
        // for (int i = 0; i <= cnt2; ++i)
        //     cout << arr[2][i] << "-----2\n";

        ll ans = 0, Min = 1e18;
        s = nn - s;
        for (int i = 0; i <= cnt1; ++i) {
            ll tmp = s - arr[1][i];
            ans = i;
            int pos = lower_bound(arr[2], arr[2] + 1 + cnt2, tmp) - arr[2];
            ans += pos * 2;
            Min = min(Min, ans);
        }
        cout << Min << '\n';
    }
    #ifndef ONLINE_JUDGE
        system("pause");
    #endif
}

/*
2
10 28
8 2 8 1
5 1 4 1
6 1 10 1
10 2 7 1
7 2 1 1
9 2 1 1
2 1 5 1
4 1 9 1
3 2 5 1

7
*/


#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map>
#include <stack>
#include <sstream>
#include <set>
// #pragma GCC optimize(2)

//#define int long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define rush() int T;scanf("%d",&T);for(int Ti=1;Ti<=T;++Ti)
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define mm(i,v) memset(i,v,sizeof i);
#define mp(a, b) make_pair(a, b)
#define pi acos(-1)
#define fi first
#define se second
//你冷静一点，确认思路再敲！！！

using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int, int > PII;
priority_queue< PII, vector<PII>, greater<PII> > que;
stringstream ssin; //  ssin << string   while ( ssin >> int)
const ll LINF = 0x7fffffffffffffffll;

const ll N = 1e6 + 5, M = 1e6 + 5, mod = 1e9 + 7, INF = 0x3f3f3f3f;
ll _, n, s, idx;
ll e[M], ne[M], h[N], w1[M], w2[M];
ll leaf[N];
vector<ll>vec[3];
ll arr[3][N];
int cnt1, cnt2;

inline ll read() {
    char c=getchar();ll x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    return x*f;
}

void init() {
    cnt1 = cnt2 = idx = 0;
    for (int i = 1; i < min(N, n + n); ++i) {
        h[i] = -1;
        leaf[i] = 0;
    }
    vec[1].clear();
    vec[2].clear();
}

struct node {
    ll u, v, w, c, num;
    double res;
    bool operator<(const node &x)const {
        return res < x.res;
    }
}E[M];

void add(ll a, ll b, ll w, ll c) {
    e[idx] = b;
    w1[idx] = w;
    w2[idx] = c;
    ne[idx] = h[a];
    h[a] = idx++;
}

void dfs(ll u, ll fa) {
    ll cnt = 0, ans = 0;
    for (int i = h[u]; ~i; i = ne[i]) {
        int v = e[i];
        if (v == fa) continue;
        dfs(v, u);
        cnt++;
        ans += leaf[v];
    }
    if (!cnt) leaf[u] = 1;
    else leaf[u] = ans;
}

bool cmp(ll x, ll y) {
    return x > y;
}

int main()
{
    // freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);
    _ = read();
    while (_--) {
        n = read(); s = read();
        init();
        for (int i = 1; i < n; ++i) {
            ll u, v, w, c;
            u = read(); v = read(); w = read(); c = read();
            E[i] = {u, v, w, c};
            add(u, v, w, c);
            add(v, u, w, c);
        }
        dfs(1, -1);
        ll nn = 0;
        for (int i = 1; i < n; ++i) {
            int a = E[i].u, b = E[i].v;
            E[i].num = min(leaf[a], leaf[b]);
            nn += E[i].num * E[i].w;
            ll now = E[i].w;
            int tmp = E[i].c;
            ll qq = E[i].num;
            while (now) {
                 //printf("now = %d push = %d\n", now, (now - now / 2) * qq);
                vec[tmp].push_back((now - now / 2) * qq);
                now /= 2;
            }
        }

        sort(vec[1].begin(), vec[1].end(), cmp);
        sort(vec[2].begin(), vec[2].end(), cmp);

        //for (int i = 0; i < vec[1].size(); ++i)
            //cout << vec[1][i] << '\n';

        for (int i = 0; i < vec[1].size(); ++i)
            arr[1][cnt1 + 1] = arr[1][cnt1] + vec[1][i], cnt1++;

        for (int i = 0; i < vec[2].size(); ++i)
            arr[2][cnt2 + 1] = arr[2][cnt2] + vec[2][i], cnt2++;

        ll ans = 0, Min = 1e18;
        s = nn - s;
        if (cnt2 == 0)
            Min = lower_bound(arr[1], arr[1] + cnt1 + 1, s) - arr[1];
        else
        for (int i = 0; i <= cnt1; ++i) {
            ll tmp = s - arr[1][i];
            if (arr[2][cnt2] < tmp)
                continue;
            ans = i;
            int pos = lower_bound(arr[2], arr[2] + 1 + cnt2, tmp) - arr[2];
            ans += pos * 2;
            Min = min(Min, ans);
        }
        cout << Min << '\n';
    }
    #ifndef ONLINE_JUDGE
        system("pause");
    #endif
}

/*
2
10 28
8 2 8 1
5 1 4 1
6 1 10 1
10 2 7 1
7 2 1 1
9 2 1 1
2 1 5 1
4 1 9 1
3 2 5 1

7
*/


#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map>
#include <stack>
#include <sstream>
#include <set>
// #pragma GCC optimize(2)

//#define int long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define rush() int T;scanf("%d",&T);for(int Ti=1;Ti<=T;++Ti)
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define mm(i,v) memset(i,v,sizeof i);
#define mp(a, b) make_pair(a, b)
#define pi acos(-1)
#define fi first
#define se second
//你冷静一点，确认思路再敲！！！

using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int, int > PII;
priority_queue< PII, vector<PII>, greater<PII> > que;
stringstream ssin; //  ssin << string   while ( ssin >> int)
const ll LINF = 0x7fffffffffffffffll;

const ll N = 3e5 + 5, M = 4e5 + 5, mod = 1e9 + 7, INF = 0x3f3f3f3f;
ll _, n, s, idx;
ll e[M], ne[M], h[N], w1[M], w2[M];
ll leaf[N];
vector<ll>vec[3];
ll arr[3][N];
int cnt1, cnt2;

inline ll read() {
    char c=getchar();ll x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    return x*f;
}

void init() {
    cnt1 = cnt2 = idx = 0;
    for (int i = 1; i < min(N, n + n); ++i) {
        h[i] = -1;
        leaf[i] = 0;
    }
    vec[1].clear();
    vec[2].clear();
}

struct node {
    ll u, v, w, c, num;
    double res;
    bool operator<(const node &x)const {
        return res < x.res;
    }
}E[M];

void add(ll a, ll b, ll w, ll c) {
    e[idx] = b;
    w1[idx] = w;
    w2[idx] = c;
    ne[idx] = h[a];
    h[a] = idx++;
}

void dfs(ll u, ll fa) {
    ll cnt = 0, ans = 0;
    for (int i = h[u]; ~i; i = ne[i]) {
        int v = e[i];
        if (v == fa) continue;
        dfs(v, u);
        cnt++;
        ans += leaf[v];
    }
    if (!cnt) leaf[u] = 1;
    else leaf[u] = ans;
}

bool cmp(ll x, ll y) {
    return x > y;
}

int main()
{
    // freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);
    _ = read();
    while (_--) {
        n = read(); s = read();
        init();
        for (int i = 1; i < n; ++i) {
            ll u, v, w, c;
            u = read(); v = read(); w = read(); c = read();
            E[i] = {u, v, w, c};
            add(u, v, w, c);
            add(v, u, w, c);
        }
        dfs(1, -1);
        ll nn = 0;
        for (int i = 1; i < n; ++i) {
            int a = E[i].u, b = E[i].v;
            E[i].num = min(leaf[a], leaf[b]);
            nn += E[i].num * E[i].w;
            ll now = E[i].w;
            int tmp = E[i].c;
            ll qq = E[i].num;
            while (now) {
                 //printf("now = %d push = %d\n", now, (now - now / 2) * qq);
                vec[tmp].push_back((now - now / 2) * qq);
                now /= 2;
            }
        }

        sort(vec[1].begin(), vec[1].end(), cmp);
        sort(vec[2].begin(), vec[2].end(), cmp);

        //for (int i = 0; i < vec[1].size(); ++i)
            //cout << vec[1][i] << '\n';

        for (int i = 0; i < vec[1].size(); ++i)
            arr[1][cnt1 + 1] = arr[1][cnt1] + vec[1][i], cnt1++;

        for (int i = 0; i < vec[2].size(); ++i)
            arr[2][cnt2 + 1] = arr[2][cnt2] + vec[2][i], cnt2++;

        ll ans = 0, Min = 1e18;
        s = nn - s;
        if (cnt2 == 0)
            Min = lower_bound(arr[1], arr[1] + cnt1 + 1, s) - arr[1];
        else
        for (int i = 0; i <= cnt1; ++i) {
            ll tmp = s - arr[1][i];
            if (arr[2][cnt2] < tmp)
                continue;
            ans = i;
            int pos = lower_bound(arr[2], arr[2] + 1 + cnt2, tmp) - arr[2];
            ans += pos * 2;
            Min = min(Min, ans);
        }
        cout << Min << '\n';
    }
    #ifndef ONLINE_JUDGE
        system("pause");
    #endif
}

/*
2
10 28
8 2 8 1
5 1 4 1
6 1 10 1
10 2 7 1
7 2 1 1
9 2 1 1
2 1 5 1
4 1 9 1
3 2 5 1

7
*/


#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map>
#include <stack>
#include <sstream>
#include <set>
// #pragma GCC optimize(2)

//#define int long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define rush() int T;scanf("%d",&T);for(int Ti=1;Ti<=T;++Ti)
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define mm(i,v) memset(i,v,sizeof i);
#define mp(a, b) make_pair(a, b)
#define pi acos(-1)
#define fi first
#define se second
//你冷静一点，确认思路再敲！！！

using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int, int > PII;
priority_queue< PII, vector<PII>, greater<PII> > que;
stringstream ssin; //  ssin << string   while ( ssin >> int)
const ll LINF = 0x7fffffffffffffffll;

const ll N = 4e5 + 5, M = 4e5 + 5, mod = 1e9 + 7, INF = 0x3f3f3f3f;
ll _, n, s, idx;
ll e[M], ne[M], h[N], w1[M], w2[M];
ll leaf[N];
vector<ll>vec[3];
ll arr[3][N];
int cnt1, cnt2;

inline ll read() {
    char c=getchar();ll x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    return x*f;
}

void init() {
    cnt1 = cnt2 = idx = 0;
    for (int i = 1; i < min(N, n + n); ++i) {
        h[i] = -1;
        leaf[i] = 0;
    }
    vec[1].clear();
    vec[2].clear();
}

struct node {
    int u, v, w, c, num;
    double res;
    bool operator<(const node &x)const {
        return res < x.res;
    }
}E[M];

void add(ll a, ll b, ll w, ll c) {
    e[idx] = b;
    w1[idx] = w;
    w2[idx] = c;
    ne[idx] = h[a];
    h[a] = idx++;
}

void dfs(ll u, ll fa) {
    ll cnt = 0, ans = 0;
    for (int i = h[u]; ~i; i = ne[i]) {
        int v = e[i];
        if (v == fa) continue;
        dfs(v, u);
        cnt++;
        ans += leaf[v];
    }
    if (!cnt) leaf[u] = 1;
    else leaf[u] = ans;
}

bool cmp(int x, int y) {
    return x > y;
}

int main()
{
    // freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);
    _ = read();
    while (_--) {
        n = read(); s = read();
        init();
        for (int i = 1; i < n; ++i) {
            ll u, v, w, c;
            u = read(); v = read(); w = read(); c = read();
            E[i] = {u, v, w, c};
            add(u, v, w, c);
            add(v, u, w, c);
        }
        dfs(1, -1);
        ll nn = 0;
        for (int i = 1; i < n; ++i) {
            int a = E[i].u, b = E[i].v;
            E[i].num = min(leaf[a], leaf[b]);
            nn += E[i].num * E[i].w;
            ll now = E[i].w;
            int tmp = E[i].c;
            ll qq = E[i].num;
            while (now) {
                 //printf("now = %d push = %d\n", now, (now - now / 2) * qq);
                vec[tmp].push_back((now - now / 2) * qq);
                now /= 2;
            }
        }

        sort(vec[1].begin(), vec[1].end(), cmp);
        sort(vec[2].begin(), vec[2].end(), cmp);

        //for (int i = 0; i < vec[1].size(); ++i)
            //cout << vec[1][i] << '\n';

        for (int i = 0; i < vec[1].size(); ++i)
            arr[1][cnt1 + 1] = arr[1][cnt1] + vec[1][i], cnt1++;

        for (int i = 0; i < vec[2].size(); ++i)
            arr[2][cnt2 + 1] = arr[2][cnt2] + vec[2][i], cnt2++;

        ll ans = 0, Min = 1e18;
        s = nn - s;
        if (cnt2 == 0)
            Min = lower_bound(arr[1], arr[1] + cnt1 + 1, s) - arr[1];
        else
        for (int i = 0; i <= cnt1; ++i) {
            ll tmp = s - arr[1][i];
            if (arr[2][cnt2] < tmp)
                continue;
            ans = i;
            int pos = lower_bound(arr[2], arr[2] + 1 + cnt2, tmp) - arr[2];
            ans += pos * 2;
            Min = min(Min, ans);
        }
        cout << Min << '\n';
    }
    #ifndef ONLINE_JUDGE
        system("pause");
    #endif
}

/*
2
10 28
8 2 8 1
5 1 4 1
6 1 10 1
10 2 7 1
7 2 1 1
9 2 1 1
2 1 5 1
4 1 9 1
3 2 5 1

7
*/


#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map>
#include <stack>
#include <sstream>
#include <set>
// #pragma GCC optimize(2)

//#define int long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define rush() int T;scanf("%d",&T);for(int Ti=1;Ti<=T;++Ti)
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define mm(i,v) memset(i,v,sizeof i);
#define mp(a, b) make_pair(a, b)
#define pi acos(-1)
#define fi first
#define se second
//你冷静一点，确认思路再敲！！！

using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int, int > PII;
priority_queue< PII, vector<PII>, greater<PII> > que;
stringstream ssin; //  ssin << string   while ( ssin >> int)
const ll LINF = 0x7fffffffffffffffll;

const ll N = 4e5 + 5, M = 4e5 + 5, mod = 1e9 + 7, INF = 0x3f3f3f3f;
ll _, n, s, idx;
ll e[M], ne[M], h[N], w1[M], w2[M];
ll leaf[N];
vector<ll>vec[3];
ll arr[3][N];
int cnt1, cnt2;

inline ll read() {
    char c=getchar();ll x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    return x*f;
}

void init() {
    cnt1 = cnt2 = idx = 0;
    for (int i = 1; i < min(N, n + n); ++i) {
        h[i] = -1;
        leaf[i] = 0;
    }
    vec[1].clear();
    vec[2].clear();
}

struct node {
    int u, v, w, c, num;
    double res;
    bool operator<(const node &x)const {
        return res < x.res;
    }
}E[M];

void add(ll a, ll b, ll w, ll c) {
    e[idx] = b;
    w1[idx] = w;
    w2[idx] = c;
    ne[idx] = h[a];
    h[a] = idx++;
}

void dfs(ll u, ll fa) {
    ll cnt = 0, ans = 0;
    for (int i = h[u]; ~i; i = ne[i]) {
        int v = e[i];
        if (v == fa) continue;
        dfs(v, u);
        cnt++;
        ans += leaf[v];
    }
    if (!cnt) leaf[u] = 1;
    else leaf[u] = ans;
}

bool cmp(int x, int y) {
    return x > y;
}

int main()
{
    // freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);
    _ = read();
    while (_--) {
        n = read(); s = read();
        init();
        for (int i = 1; i < n; ++i) {
            ll u, v, w, c;
            u = read(); v = read(); w = read(); c = read();
            E[i] = {u, v, w, c};
            add(u, v, w, c);
            add(v, u, w, c);
        }
        dfs(1, -1);
        ll nn = 0;
        for (int i = 1; i < n; ++i) {
            int a = E[i].u, b = E[i].v;
            E[i].num = min(leaf[a], leaf[b]);
            nn += E[i].num * E[i].w;
            ll now = E[i].w;
            int tmp = E[i].c;
            ll qq = E[i].num;
            while (now) {
                 //printf("now = %d push = %d\n", now, (now - now / 2) * qq);
                vec[tmp].push_back((now - now / 2) * qq);
                now /= 2;
            }
        }

        sort(vec[1].begin(), vec[1].end(), cmp);
        sort(vec[2].begin(), vec[2].end(), cmp);

        //for (int i = 0; i < vec[1].size(); ++i)
            //cout << vec[1][i] << '\n';

        for (int i = 0; i < vec[1].size(); ++i)
            arr[1][cnt1 + 1] = arr[1][cnt1] + vec[1][i], cnt1++;

        for (int i = 0; i < vec[2].size(); ++i)
            arr[2][cnt2 + 1] = arr[2][cnt2] + vec[2][i], cnt2++;

        ll ans = 0, Min = 1e18;
        s = nn - s;
        for (int i = 0; i <= cnt1; ++i) {
            ll tmp = s - arr[1][i];
            ans = i;
            int pos = lower_bound(arr[2], arr[2] + 1 + cnt2, tmp) - arr[2];
            if (pos > cnt2)continue;
            ans += pos * 2;
            Min = min(Min, ans);
        }
        cout << Min << '\n';
    }
    #ifndef ONLINE_JUDGE
        system("pause");
    #endif
}

/*
2
10 28
8 2 8 1
5 1 4 1
6 1 10 1
10 2 7 1
7 2 1 1
9 2 1 1
2 1 5 1
4 1 9 1
3 2 5 1

7
*/


#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map>
#include <stack>
#include <sstream>
#include <set>
// #pragma GCC optimize(2)

//#define int long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define rush() int T;scanf("%d",&T);for(int Ti=1;Ti<=T;++Ti)
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define mm(i,v) memset(i,v,sizeof i);
#define mp(a, b) make_pair(a, b)
#define pi acos(-1)
#define fi first
#define se second
//你冷静一点，确认思路再敲！！！

using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int, int > PII;
priority_queue< PII, vector<PII>, greater<PII> > que;
stringstream ssin; //  ssin << string   while ( ssin >> int)
const ll LINF = 0x7fffffffffffffffll;

const ll N = 4e5 + 5, M = 4e5 + 5, mod = 1e9 + 7, INF = 0x3f3f3f3f;
ll _, n, s, idx;
ll e[M], ne[M], h[N], w1[M], w2[M];
ll leaf[N];

inline ll read() {
    char c=getchar();ll x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    return x*f;
}

void init() {
    idx = 0;
    for (int i = 1; i < min(N, n + n); ++i) h[i] = -1;
}

struct node {
    int u, v, w, c, num;
    double res;
    bool operator<(const node &x)const {
        return res < x.res;
    }
}E[M];

void add(ll a, ll b, ll w, ll c) {
    e[idx] = b;
    w1[idx] = w;
    w2[idx] = c;
    ne[idx] = h[a];
    h[a] = idx++;
}

void dfs(ll u, ll fa) {
    ll cnt = 0, ans = 0;
    for (int i = h[u]; ~i; i = ne[i]) {
        int v = e[i];
        if (v == fa) continue;
        dfs(v, u);
        cnt++;
        ans += leaf[v];
    }
    if (!cnt) leaf[u] = 1;
    else leaf[u] = ans;
}

int main()
{
    // freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);
    _ = read();
    while (_--) {
        n = read(); s = read();
        init();
        for (int i = 1; i < n; ++i) {
            ll u, v, w, c;
            u = read(); v = read(); w = read(); c = read();
            E[i] = {u, v, w, c};
            add(u, v, w, c);
            add(v, u, w, c);
        }
        dfs(1, -1);
        ll now = 0;
        priority_queue<node>q;
        for (int i = 1; i < n; ++i) {
            int a = E[i].u, b = E[i].v;
            E[i].num = min(leaf[a], leaf[b]);
            now += E[i].num * E[i].w;
            E[i].res = 1.0 * (E[i].w - E[i].w / 2) * E[i].num / E[i].c;
            q.push(E[i]);
        }

        // while (!q.empty()) {
        //     node t = q.top();
        //     q.pop();
        //     printf("%d %d %d %d %d %lf\n", t.u, t.v, t.w, t.c, t.num, t.res);
        // }
        // continue;

        ll ans = 0;
        // cout << now << '\n';
        while (now > s) {
            node tt, t;
            t = q.top();
            if (t.w == 0) continue;
            // printf("%d %d %d %d %d %lf\n", t.u, t.v, t.w, t.c, t.num, t.res);
            tt = t;
            q.pop();
            ans += t.c;
            now -= t.num * (t.w - t.w / 2);
            tt.w = t.w / 2;
            tt.res = 1.0 * (tt.w - tt.w / 2) * tt.num / tt.c;
            q.push(tt);
        }
        // cout << now << '\n';
        cout << ans << '\n';
    }
    #ifndef ONLINE_JUDGE
        system("pause");
    #endif
}

/*
2
10 28
8 2 8 1
5 1 4 1
6 1 10 1
10 2 7 1
7 2 1 1
9 2 1 1
2 1 5 1
4 1 9 1
3 2 5 1

7
*/


#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map>
#include <stack>
#include <sstream>
#include <set>
// #pragma GCC optimize(2)

//#define int long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define rush() int T;scanf("%d",&T);for(int Ti=1;Ti<=T;++Ti)
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define mm(i,v) memset(i,v,sizeof i);
#define mp(a, b) make_pair(a, b)
#define pi acos(-1)
#define fi first
#define se second
//你冷静一点，确认思路再敲！！！

using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int, int > PII;
priority_queue< PII, vector<PII>, greater<PII> > que;
stringstream ssin; //  ssin << string   while ( ssin >> int)
const ll LINF = 0x7fffffffffffffffll;

const ll N = 4e5 + 5, M = 4e5 + 5, mod = 1e9 + 7, INF = 0x3f3f3f3f;
ll _, n, s, idx;
ll e[M], ne[M], h[N], w1[M], w2[M];
ll leaf[N];
vector<ll>vec[3];
ll arr[3][N];
int cnt1, cnt2;

inline ll read() {
    char c=getchar();ll x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    return x*f;
}

void init() {
    cnt1 = cnt2 = idx = 0;
    for (int i = 1; i < min(N, n + n); ++i) {
        h[i] = -1;
        leaf[i] = 0;
    }
    vec[1].clear();
    vec[2].clear();
}

struct node {
    int u, v, w, c, num;
    double res;
    bool operator<(const node &x)const {
        return res < x.res;
    }
}E[M];

void add(ll a, ll b, ll w, ll c) {
    e[idx] = b;
    w1[idx] = w;
    w2[idx] = c;
    ne[idx] = h[a];
    h[a] = idx++;
}

void dfs(ll u, ll fa) {
    ll cnt = 0, ans = 0;
    for (int i = h[u]; ~i; i = ne[i]) {
        int v = e[i];
        if (v == fa) continue;
        dfs(v, u);
        cnt++;
        ans += leaf[v];
    }
    if (!cnt) leaf[u] = 1;
    else leaf[u] = ans;
}

bool cmp(int x, int y) {
    return x > y;
}

int main()
{
    // freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);
    _ = read();
    while (_--) {
        n = read(); s = read();
        init();
        for (int i = 1; i < n; ++i) {
            ll u, v, w, c;
            u = read(); v = read(); w = read(); c = read();
            E[i] = {u, v, w, c};
            add(u, v, w, c);
            add(v, u, w, c);
        }
        dfs(1, -1);
        ll nn = 0;
        for (int i = 1; i < n; ++i) {
            int a = E[i].u, b = E[i].v;
            E[i].num = min(leaf[a], leaf[b]);
            nn += E[i].num * E[i].w;
            ll now = E[i].w;
            int tmp = E[i].c;
            ll qq = E[i].num;
            while (now) {
                 //printf("now = %d push = %d\n", now, (now - now / 2) * qq);
                vec[tmp].push_back((now - now / 2) * qq);
                now /= 2;
            }
        }

        sort(vec[1].begin(), vec[1].end(), cmp);
        sort(vec[2].begin(), vec[2].end(), cmp);

        //for (int i = 0; i < vec[1].size(); ++i)
            //cout << vec[1][i] << '\n';

        for (int i = 0; i < vec[1].size(); ++i)
            arr[1][cnt1 + 1] = arr[1][cnt1] + vec[1][i], cnt1++;

        for (int i = 0; i < vec[2].size(); ++i)
            arr[2][cnt2 + 1] = arr[2][cnt2] + vec[2][i], cnt2++;

        ll ans = 0, Min = 1e18;
        s = nn - s;
        for (int i = 0; i <= cnt1; ++i) {
            ll tmp = s - arr[1][i];
            if (arr[2][cnt2] < tmp)
                continue;
            ans = i;
            int pos = lower_bound(arr[2], arr[2] + 1 + cnt2, tmp) - arr[2];
            //if (pos > cnt2)continue;
            ans += pos * 2;
            Min = min(Min, ans);
        }
        cout << Min << '\n';
    }
    #ifndef ONLINE_JUDGE
        system("pause");
    #endif
}

/*
2
10 28
8 2 8 1
5 1 4 1
6 1 10 1
10 2 7 1
7 2 1 1
9 2 1 1
2 1 5 1
4 1 9 1
3 2 5 1

7
*/


#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map>
#include <stack>
#include <sstream>
#include <set>
// #pragma GCC optimize(2)

//#define int long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define rush() int T;scanf("%d",&T);for(int Ti=1;Ti<=T;++Ti)
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define mm(i,v) memset(i,v,sizeof i);
#define mp(a, b) make_pair(a, b)
#define pi acos(-1)
#define fi first
#define se second
//你冷静一点，确认思路再敲！！！

using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int, int > PII;
priority_queue< PII, vector<PII>, greater<PII> > que;
stringstream ssin; //  ssin << string   while ( ssin >> int)
const ll LINF = 0x7fffffffffffffffll;

const ll N = 4e5 + 5, M = 4e5 + 5, mod = 1e9 + 7, INF = 0x3f3f3f3f;
ll _, n, s, idx;
ll e[M], ne[M], h[N], w1[M], w2[M];
ll leaf[N];
vector<ll>vec[3];
ll arr[3][N];
int cnt1, cnt2;

inline ll read() {
    char c=getchar();ll x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    return x*f;
}

void init() {
    cnt1 = cnt2 = idx = 0;
    for (int i = 1; i < min(N, n + n); ++i) {
        h[i] = -1;
        leaf[i] = 0;
    }
    vec[1].clear();
    vec[2].clear();
}

struct node {
    ll u, v, w, c, num;
    double res;
    bool operator<(const node &x)const {
        return res < x.res;
    }
}E[M];

void add(ll a, ll b, ll w, ll c) {
    e[idx] = b;
    w1[idx] = w;
    w2[idx] = c;
    ne[idx] = h[a];
    h[a] = idx++;
}

void dfs(ll u, ll fa) {
    ll cnt = 0, ans = 0;
    for (int i = h[u]; ~i; i = ne[i]) {
        int v = e[i];
        if (v == fa) continue;
        dfs(v, u);
        cnt++;
        ans += leaf[v];
    }
    if (!cnt) leaf[u] = 1;
    else leaf[u] = ans;
}

bool cmp(int x, int y) {
    return x > y;
}

int main()
{
    // freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);
    _ = read();
    while (_--) {
        n = read(); s = read();
        init();
        for (int i = 1; i < n; ++i) {
            ll u, v, w, c;
            u = read(); v = read(); w = read(); c = read();
            E[i] = {u, v, w, c};
            add(u, v, w, c);
            add(v, u, w, c);
        }
        dfs(1, -1);
        ll nn = 0;
        for (int i = 1; i < n; ++i) {
            int a = E[i].u, b = E[i].v;
            E[i].num = min(leaf[a], leaf[b]);
            nn += E[i].num * E[i].w;
            ll now = E[i].w;
            int tmp = E[i].c;
            ll qq = E[i].num;
            while (now) {
                 //printf("now = %d push = %d\n", now, (now - now / 2) * qq);
                vec[tmp].push_back((now - now / 2) * qq);
                now /= 2;
            }
        }

        sort(vec[1].begin(), vec[1].end(), cmp);
        sort(vec[2].begin(), vec[2].end(), cmp);

        //for (int i = 0; i < vec[1].size(); ++i)
            //cout << vec[1][i] << '\n';

        for (int i = 0; i < vec[1].size(); ++i)
            arr[1][cnt1 + 1] = arr[1][cnt1] + vec[1][i], cnt1++;

        for (int i = 0; i < vec[2].size(); ++i)
            arr[2][cnt2 + 1] = arr[2][cnt2] + vec[2][i], cnt2++;

        ll ans = 0, Min = 1e18;
        s = nn - s;
        if (cnt2 == 0)
            Min = lower_bound(arr[1], arr[1] + cnt1 + 1, s) - arr[1];
        else
        for (int i = 0; i <= cnt1; ++i) {
            ll tmp = s - arr[1][i];
            if (arr[2][cnt2] < tmp)
                continue;
            ans = i;
            int pos = lower_bound(arr[2], arr[2] + 1 + cnt2, tmp) - arr[2];
            ans += pos * 2;
            Min = min(Min, ans);
        }
        cout << Min << '\n';
    }
    #ifndef ONLINE_JUDGE
        system("pause");
    #endif
}

/*
2
10 28
8 2 8 1
5 1 4 1
6 1 10 1
10 2 7 1
7 2 1 1
9 2 1 1
2 1 5 1
4 1 9 1
3 2 5 1

7
*/


#include<iostream>
#include<cstdio>
#include<vector>
#include<set>
using namespace std;
#define pii pair<int,int>
#define x first
#define y second
namespace IO
{
    void read(int &x)
    {
        x=0;
        int f=1;
        char c=getchar();
        while('0'>c||c>'9')
        {
            if(c=='-')
                f=-1;
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        x*=f;
    }
    void read(long long &x)
    {
        x=0;
        int f=1;
        char c=getchar();
        while('0'>c||c>'9')
        {
            if(c=='-')
                f=-1;
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        x*=f;
    }
    void write(int x)
    {
        if(x>9)
            write(x/10);
        putchar(x%10+'0');
    }
    void write(long long x)
    {
        if(x>9)
            write(x/10);
        putchar(x%10+'0');
    }
}
using namespace IO;
struct node
{
    int e;
    int w,c;
};
struct node_set
{
    int s;
    int len;
    friend bool operator < (const node_set &a,const node_set &b)
    {
        return 1ll*a.s*a.len>1ll*b.s*b.len;
    }
};
int T;
int n,cnt;
int w;
long long s;
long long now;
vector<node> g[100005];
int st[100005],ed[100005];
multiset<node_set> t[3];
void init()
{
    w=0;now=0;cnt=0;
    t[1].clear();t[2].clear();
    for(int i=1;i<=n;i++)
        g[i].clear();
}
void dfs(int u,int fa)
{
    if(g[u].size()==1&&g[u].back().e==fa)
    {
        cnt++;
		st[u]=cnt;
	}
	else
		st[u]=(1ll<<30);

	for(int i=0;i<g[u].size();i++)
    {
        int v=g[u][i].e;
        if(v!=fa)
        {
            dfs(v,u);
            st[u]=min(st[u],st[v]);
            t[g[u][i].c].insert((node_set){g[u][i].w,ed[v]-st[v]+1});
            now=now+1ll*g[u][i].w*(ed[v]-st[v]+1);
        }
    }
    ed[u]=cnt;
}
void c_in()
{
    cin>>n>>s;
    init();
    for(int i=1;i<n;i++)
    {
        int u,v,w,c;
        read(u);read(v);
        read(w);read(c);
        g[u].push_back((node){v,w,c});g[v].push_back((node){u,w,c});
    }
    dfs(1,0);
    //cout<<"now:"<<now<<'\n';
    if(now<=s)
    {
        write(0);
        putchar('\n');
        return;
    }
    if(t[2].size()==0)
    {
        while(now>s)
        {
            node_set temp=(*t[1].begin());t[1].erase(temp);
            t[1].insert((node_set){temp.s/2,temp.len});
            now=now-(1ll*temp.s*temp.len-(1ll*temp.s)/2*temp.len);
            w+=2;
        }
        write(w);
        putchar('\n');
        return;
    }
    if(t[1].size()==0)
    {
        while(now>s)
        {
            node_set temp=(*t[2].begin());t[2].erase(temp);
            t[2].insert((node_set){temp.s/2,temp.len});
            now=now-(1ll*temp.s*temp.len-(1ll*temp.s)/2*temp.len);
            w++;
        }
        write(w);
        putchar('\n');
        return;
    }
    while(1)
    {
        node_set temp1,temp2,temp3;
        temp1=(*t[1].begin());t[1].erase(temp1);
        t[1].insert((node_set){temp1.s/2,temp1.len});

        temp2=(*t[1].begin());t[1].erase(temp2);
        t[1].insert((node_set){temp2.s/2,temp2.len});

        temp3=(*t[2].begin());t[2].erase(temp3);
        t[2].insert((node_set){temp3.s/2,temp3.len});
        if(now-1ll*temp1.s*temp1.len<=s)
        {
            w++;
            break;
        }
        w+=2;
        if(1ll*temp1.s*temp1.len+1ll*temp2.s*temp2.len-(1ll*temp1.s/2)*temp1.len-(1ll*temp2.s/2)*temp2.len<1ll*temp3.s*temp3.len-(1ll*temp3.s/2)*temp3.len)
        {
        	now=now-(1ll*temp3.s*temp3.len-(1ll*temp3.s/2)*temp3.len);
            t[1].erase((node_set){temp1.s/2,temp1.len});t[1].erase((node_set){temp2.s/2,temp2.len});
            t[1].insert(temp1);t[1].insert(temp2);
        }
        else
        {
        	now=now-(1ll*temp1.s*temp1.len+1ll*temp2.s*temp2.len-(1ll*temp1.s/2)*temp1.len-(1ll*temp2.s/2)*temp2.len);
            t[2].erase((node_set){temp3.s/2,temp3.len});
            t[2].insert(temp3);
        }
    }
    write(w);
    putchar('\n');
}
int main()
{
    cin>>T;
    for(int i=1;i<=T;i++)
        c_in();
    return 0;
}
/*
200
10 120
3 1 8 1
5 2 10 1
8 1 5 1
2 1 6 1
7 2 8 1
10 7 7 1
6 4 10 1
4 3 10 1
9 7 9 1
10 97
3 1 1 1
5 1 9 1
6 3 6 1
4 3 5 1
2 1 4 1
7 6 10 1
10 6 8 1
9 8 3 1
8 5 1 1
10 119
5 4 9 1
10 8 1 1
4 3 10 1
6 5 1 1
3 2 1 1
8 7 7 1
2 1 2 1
9 7 4 1
7 6 9 1
10 28
8 2 8 1
5 1 4 1
6 1 10 1
10 2 7 1
7 2 1 1
9 2 1 1
2 1 5 1
4 1 9 1
3 2 5 1
*/


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<set>
using namespace std;
#define pii pair<int,int>
#define x first
#define y second
namespace IO
{
    void read(int &x)
    {
        x=0;
        int f=1;
        char c=getchar();
        while('0'>c||c>'9')
        {
            if(c=='-')
                f=-1;
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        x*=f;
    }
    void read(long long &x)
    {
        x=0;
        int f=1;
        char c=getchar();
        while('0'>c||c>'9')
        {
            if(c=='-')
                f=-1;
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        x*=f;
    }
    void write(int x)
    {
        if(x>9)
            write(x/10);
        putchar(x%10+'0');
    }
    void write(long long x)
    {
        if(x>9)
            write(x/10);
        putchar(x%10+'0');
    }
}
using namespace IO;
struct node
{
    int e;
    int w,c;
};
struct node_set
{
    int s;
    int len;
    friend bool operator < (const node_set &a,const node_set &b)
    {
        return 1ll*a.s*a.len>1ll*b.s*b.len;
    }
};
int T;
int n,cnt;
int w;
long long s;
long long now;
vector<node> g[100005];
int st[100005],ed[100005];
vector<node_set> t[3];
long long pre[100005];
void init()
{
    w=(1ll<<30);now=0;cnt=0;
    t[1].clear();t[2].clear();
    for(int i=1;i<=n;i++)
        g[i].clear();
}
void dfs(int u,int fa)
{
    if(g[u].size()==1&&g[u].back().e==fa)
    {
        cnt++;
		st[u]=cnt;
	}
	else
		st[u]=(1ll<<30);

	for(int i=0;i<g[u].size();i++)
    {
        int v=g[u][i].e;
        if(v!=fa)
        {
            dfs(v,u);
            st[u]=min(st[u],st[v]);
            t[g[u][i].c].push_back((node_set){g[u][i].w,ed[v]-st[v]+1});
            now=now+1ll*g[u][i].w*(ed[v]-st[v]+1);
        }
    }
    ed[u]=cnt;
}
int check(long long now)
{
	if(t[2].size()==0)
		return (1ll<<30);
    int l=0,r=t[2].size()-1,mid;
	if(now-pre[r]>s)
		return (1ll<<30);
    while(l+1<r)
    {
        mid=(l+r)>>1;
        if(now-pre[mid]<=s)
            r=mid;
        else
            l=mid;
    }
    while(now-pre[r-1]<=s)
        r--;
    return (r+1)*2;
}
void c_in()
{
    cin>>n>>s;
    init();
    for(int i=1;i<n;i++)
    {
        int u,v,w,c;
        read(u);read(v);
        read(w);read(c);
        g[u].push_back((node){v,w,c});g[v].push_back((node){u,w,c});
    }
    dfs(1,0);
    if(now<=s)
    {
    	write(0);
    	putchar('\n');
    	return;
	}
    int len1=t[1].size(),len2=t[2].size();
    for(int i=0;i<len1;i++)
    {
        int now=t[1][i].s;
        while(now/2)
        {
            now/=2;
            t[1].push_back((node_set){now,t[1][i].len});
        }
    }
    for(int i=0;i<len2;i++)
    {
        int now=t[2][i].s;
        while(now/2)
        {
            now/=2;
            t[2].push_back((node_set){now,t[2][i].len});
        }
    }
    sort(t[1].begin(),t[1].end());sort(t[2].begin(),t[2].end());
    if(t[2].size())
    {
    	pre[0]=1ll*t[2][0].s*t[2][0].len-(1ll*t[2][0].s/2)*t[2][0].len;
    	for(int i=1;i<t[2].size();i++)
         	pre[i]=pre[i-1]+(1ll*t[2][i].s*t[2][i].len-(1ll*t[2][i].s/2)*t[2][i].len);
	}
    w=check(now);
	for(int i=0;i<t[1].size();i++)
    {
        now=now-(1ll*t[1][i].s*t[1][i].len-(1ll*t[1][i].s/2)*t[1][i].len);
        if(now<=s)
        {
            w=min(w,i+1);
            break;
        }
        w=min(w,i+1+check(now));
    }
    write(w);putchar('\n');
}
int main()
{
    cin>>T;
    for(int i=1;i<=T;i++)
        c_in();
    return 0;
}
/*
1
10 19158
1 2 15661 1
1 3 7460 1
2 4 8989 2
1 5 1602 2
2 6 19664 2
3 7 5276 1
5 8 24070 1
5 9 17520 2
2 10 28763 2
*/


#include<iostream>
#include<cstdio>
#include<vector>
#include<set>
using namespace std;
#define pii pair<int,int>
#define x first
#define y second
namespace IO
{
    void read(int &x)
    {
        x=0;
        int f=1;
        char c=getchar();
        while('0'>c||c>'9')
        {
            if(c=='-')
                f=-1;
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        x*=f;
    }
    void read(long long &x)
    {
        x=0;
        int f=1;
        char c=getchar();
        while('0'>c||c>'9')
        {
            if(c=='-')
                f=-1;
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        x*=f;
    }
    void write(int x)
    {
        if(x>9)
            write(x/10);
        putchar(x%10+'0');
    }
    void write(long long x)
    {
        if(x>9)
            write(x/10);
        putchar(x%10+'0');
    }
}
using namespace IO;
struct node
{
    int e;
    int w,c;
};
struct node_set
{
    int s;
    int len;
    friend bool operator < (const node_set &a,const node_set &b)
    {
        return 1ll*a.s*a.len>1ll*b.s*a.len;
    }
};
int T;
int n,cnt;
int w;
long long s;
long long now;
vector<node> g[100005];
int st[100005],ed[100005];
multiset<node_set> t[3];
void init()
{
    w=0;now=0;cnt=0;
    t[1].clear();t[2].clear();
    for(int i=1;i<=n;i++)
        g[i].clear();
}
void dfs(int u,int fa)
{
    if(g[u].size()==1&&g[u].back().e==fa)
    {
        cnt++;
		st[u]=cnt;
	}
	else
		st[u]=(1ll<<30);

	for(int i=0;i<g[u].size();i++)
    {
        int v=g[u][i].e;
        if(v!=fa)
        {
            dfs(v,u);
            st[u]=min(st[u],st[v]);
            t[g[u][i].c].insert((node_set){g[u][i].w,ed[v]-st[v]+1});
            now=now+1ll*g[u][i].w*(ed[v]-st[v]+1);
        }
    }
    ed[u]=cnt;
}
void c_in()
{
    cin>>n>>s;
    init();
    for(int i=1;i<n;i++)
    {
        int u,v,w,c;
        read(u);read(v);
        read(w);read(c);
        g[u].push_back((node){v,w,c});g[v].push_back((node){u,w,c});
    }
    dfs(1,0);
    //cout<<"now:"<<now<<'\n';
    if(now<=s)
    {
        write(0);
        putchar('\n');
        return;
    }
    if(t[2].size()==0)
    {
        while(now>s)
        {
            node_set temp=(*t[1].begin());t[1].erase(temp);
            t[1].insert((node_set){temp.s/2,temp.len});
            now=now-(1ll*temp.s*temp.len-(1ll*temp.s)/2*temp.len);
            w++;
        }
        write(w);
        putchar('\n');
        return;
    }
    if(t[1].size()==0)
    {
        while(now>s)
        {
            node_set temp=(*t[2].begin());t[2].erase(temp);
            t[2].insert((node_set){temp.s/2,temp.len});
            now=now-(1ll*temp.s*temp.len-(1ll*temp.s)/2*temp.len);
            w+=2;
        }
        write(w);
        putchar('\n');
        return;
    }
    while(1)
    {
        node_set temp1,temp2,temp3;
        temp1=(*t[1].begin());t[1].erase(temp1);
        t[1].insert((node_set){temp1.s/2,temp1.len});

        temp2=(*t[1].begin());t[1].erase(temp2);
        t[1].insert((node_set){temp2.s/2,temp2.len});

        temp3=(*t[2].begin());t[2].erase(temp3);
        t[2].insert((node_set){temp3.s/2,temp3.len});
        if(now-1ll*temp1.s*temp1.len<=s)
        {
            w++;
            break;
        }
        w+=2;
        if(1ll*temp1.s*temp1.len+1ll*temp2.s*temp2.len-(1ll*temp1.s/2)*temp1.len-(1ll*temp2.s/2)*temp2.len<1ll*temp3.s*temp3.len-(1ll*temp3.s/2)*temp3.len)
        {
        	now=now-(1ll*temp3.s*temp3.len-(1ll*temp3.s/2)*temp3.len);
            t[1].erase((node_set){temp1.s/2,temp1.len});t[1].erase((node_set){temp2.s/2,temp2.len});
            t[1].insert(temp1);t[1].insert(temp2);
        }
        else
        {
        	now=now-(1ll*temp1.s*temp1.len+1ll*temp2.s*temp2.len-(1ll*temp1.s/2)*temp1.len-(1ll*temp2.s/2)*temp2.len);
            t[2].erase((node_set){temp3.s/2,temp3.len});
            t[2].insert(temp3);
        }
    }
    write(w);
    putchar('\n');
}
int main()
{
    cin>>T;
    for(int i=1;i<=T;i++)
        c_in();
    return 0;
}


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<set>
using namespace std;
#define pii pair<int,int>
#define x first
#define y second
namespace IO
{
    void read(int &x)
    {
        x=0;
        int f=1;
        char c=getchar();
        while('0'>c||c>'9')
        {
            if(c=='-')
                f=-1;
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        x*=f;
    }
    void read(long long &x)
    {
        x=0;
        int f=1;
        char c=getchar();
        while('0'>c||c>'9')
        {
            if(c=='-')
                f=-1;
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        x*=f;
    }
    void write(int x)
    {
        if(x>9)
            write(x/10);
        putchar(x%10+'0');
    }
    void write(long long x)
    {
        if(x>9)
            write(x/10);
        putchar(x%10+'0');
    }
}
using namespace IO;
struct node
{
    int e;
    int w,c;
};
struct node_set
{
    int s;
    int len;
    friend bool operator < (const node_set &a,const node_set &b)
    {
        return 1ll*a.s*a.len>1ll*b.s*b.len;
    }
};
int T;
int n,cnt;
int w;
long long s;
long long now;
vector<node> g[100005];
int st[100005],ed[100005];
vector<node_set> t[3];
long long pre[100005];
void init()
{
    w=(1ll<<30);now=0;cnt=0;
    t[1].clear();t[2].clear();
    for(int i=1;i<=n;i++)
        g[i].clear();
}
void dfs(int u,int fa)
{
    if(g[u].size()==1&&g[u].back().e==fa)
    {
        cnt++;
		st[u]=cnt;
	}
	else
		st[u]=(1ll<<30);

	for(int i=0;i<g[u].size();i++)
    {
        int v=g[u][i].e;
        if(v!=fa)
        {
            dfs(v,u);
            st[u]=min(st[u],st[v]);
            t[g[u][i].c].push_back((node_set){g[u][i].w,ed[v]-st[v]+1});
            now=now+1ll*g[u][i].w*(ed[v]-st[v]+1);
        }
    }
    ed[u]=cnt;
}
int check(long long now)
{
	if(t[2].size()==0)
		return (1ll<<30);
    int l=0,r=t[2].size()-1,mid;
	if(now-pre[r]>s)
		return (1ll<<30);
    while(l+1<r)
    {
        mid=(l+r)>>1;
        if(now-pre[mid]<=s)
            r=mid;
        else
            l=mid;
    }
    while(now-pre[r-1]<=s)
        r--;
    return (r+1)*2;
}
void c_in()
{
    cin>>n>>s;
    init();
    for(int i=1;i<n;i++)
    {
        int u,v,w,c;
        read(u);read(v);
        read(w);read(c);
        g[u].push_back((node){v,w,c});g[v].push_back((node){u,w,c});
    }
    dfs(1,0);
    if(now<=s)
    {
    	write(0);
    	putchar('\n');
    	return;
	}
    int len1=t[1].size(),len2=t[2].size();
    for(int i=0;i<len1;i++)
    {
        int now=t[1][i].s;
        while(now/2)
        {
            now/=2;
            t[1].push_back((node_set){now,t[1][i].len});
        }
    }
    for(int i=0;i<len2;i++)
    {
        int now=t[2][i].s;
        while(now/2)
        {
            now/=2;
            t[2].push_back((node_set){now,t[2][i].len});
        }
    }
    sort(t[1].begin(),t[1].end());sort(t[2].begin(),t[2].end());
    if(t[2].size())
    {
    	pre[0]=1ll*t[2][0].s*t[2][0].len-(1ll*t[2][0].s/2)*t[2][0].len;
    	for(int i=1;i<t[2].size();i++)
         	pre[i]=pre[i-1]+(1ll*t[2][i].s*t[2][i].len-(1ll*t[2][i].s/2)*t[2][i].len);
	}
    w=check(now);
	for(int i=0;i<t[1].size();i++)
    {
        now=now-(1ll*t[1][i].s*t[1][i].len-(1ll*t[1][i].s/2)*t[1][i].len);
        if(now<=s)
        {
            w=min(w,i);
            break;
        }
        w=min(w,i+1+check(now));
    }
    write(w);putchar('\n');
}
int main()
{
    cin>>T;
    for(int i=1;i<=T;i++)
        c_in();
    return 0;
}
/*
1
10 19158
1 2 15661 1
1 3 7460 1
2 4 8989 2
1 5 1602 2
2 6 19664 2
3 7 5276 1
5 8 24070 1
5 9 17520 2
2 10 28763 2
*/


#include<iostream>
#include<cstdio>
#include<vector>
#include<set>
using namespace std;
#define pii pair<int,int>
#define x first
#define y second
namespace IO
{
    void read(int &x)
    {
        x=0;
        int f=1;
        char c=getchar();
        while('0'>c||c>'9')
        {
            if(c=='-')
                f=-1;
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        x*=f;
    }
    void read(long long &x)
    {
        x=0;
        int f=1;
        char c=getchar();
        while('0'>c||c>'9')
        {
            if(c=='-')
                f=-1;
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        x*=f;
    }
    void write(int x)
    {
        if(x>9)
            write(x/10);
        putchar(x%10+'0');
    }
    void write(long long x)
    {
        if(x>9)
            write(x/10);
        putchar(x%10+'0');
    }
}
using namespace IO;
struct node
{
    int e;
    int w,c;
};
struct node_set
{
    int s;
    int len;
    friend bool operator < (const node_set &a,const node_set &b)
    {
        return 1ll*a.s*a.len>1ll*b.s*b.len;
    }
};
int T;
int n,cnt;
int w;
long long s;
long long now;
vector<node> g[100005];
int st[100005],ed[100005];
multiset<node_set> t[3];
void init()
{
    w=0;now=0;cnt=0;
    t[1].clear();t[2].clear();
    for(int i=1;i<=n;i++)
        g[i].clear();
}
void dfs(int u,int fa)
{
    if(g[u].size()==1&&g[u].back().e==fa)
    {
        cnt++;
		st[u]=cnt;
	}
	else
		st[u]=(1ll<<30);

	for(int i=0;i<g[u].size();i++)
    {
        int v=g[u][i].e;
        if(v!=fa)
        {
            dfs(v,u);
            st[u]=min(st[u],st[v]);
            t[g[u][i].c].insert((node_set){g[u][i].w,ed[v]-st[v]+1});
            now=now+1ll*g[u][i].w*(ed[v]-st[v]+1);
        }
    }
    ed[u]=cnt;
}
void c_in()
{
    cin>>n>>s;
    init();
    for(int i=1;i<n;i++)
    {
        int u,v,w,c;
        read(u);read(v);
        read(w);read(c);
        g[u].push_back((node){v,w,c});g[v].push_back((node){u,w,c});
    }
    dfs(1,0);
    if(now<=s)
    {
        write(0);
        putchar('\n');
        return;
    }
    if(t[2].size()==0)
    {
        while(now>s)
        {
            node_set temp=(*t[1].begin());t[1].erase(temp);
            t[1].insert((node_set){temp.s/2,temp.len});
            now=now-(1ll*temp.s*temp.len-(1ll*temp.s)/2*temp.len);
            w++;
        }
        write(w);
        putchar('\n');
        return;
    }
    if(t[1].size()==0)
    {
        while(now>s)
        {
            node_set temp=(*t[2].begin());t[2].erase(temp);
            t[2].insert((node_set){temp.s/2,temp.len});
            now=now-(1ll*temp.s*temp.len-(1ll*temp.s)/2*temp.len);
            w+=2;
        }
        write(w);
        putchar('\n');
        return;
    }
    while(now>s)
    {
        node_set temp1,temp2,temp3;
        temp1=(*t[1].begin());t[1].erase(temp1);
        t[1].insert((node_set){temp1.s/2,temp1.len});

        temp2=(*t[1].begin());t[1].erase(temp2);
        t[1].insert((node_set){temp2.s/2,temp2.len});

        temp3=(*t[2].begin());t[2].erase(temp3);
        t[2].insert((node_set){temp3.s/2,temp3.len});

        if(now-(1ll*temp1.s*temp1.len-(1ll*temp1.s/2)*temp1.len)<=s)
        {
            w++;
            break;
        }
        w+=2;
        if(1ll*temp1.s*temp1.len+1ll*temp2.s*temp2.len-(1ll*temp1.s/2)*temp1.len-(1ll*temp2.s/2)*temp2.len<1ll*temp3.s*temp3.len-(1ll*temp3.s/2)*temp3.len)
        {
        	now=now-(1ll*temp3.s*temp3.len-(1ll*temp3.s/2)*temp3.len);
            t[1].erase((node_set){temp1.s/2,temp1.len});t[1].erase((node_set){temp2.s/2,temp2.len});
            t[1].insert(temp1);t[1].insert(temp2);
        }
        else
        {
        	now=now-(1ll*temp1.s*temp1.len+1ll*temp2.s*temp2.len-(1ll*temp1.s/2)*temp1.len-(1ll*temp2.s/2)*temp2.len);
            t[2].erase((node_set){temp3.s/2,temp3.len});
            t[2].insert(temp3);
        }
    }
    write(w);
    putchar('\n');
}
int main()
{
    cin>>T;
    for(int i=1;i<=T;i++)
        c_in();
    return 0;
}
/*
1
10 19158
1 2 15661 1
1 3 7460 1
2 4 8989 2
1 5 1602 2
2 6 19664 2
3 7 5276 1
5 8 24070 1
5 9 17520 2
2 10 28763 2
*/


#include<iostream>
#include<cstdio>
#include<vector>
#include<set>
using namespace std;
#define pii pair<int,int>
#define x first
#define y second
namespace IO
{
    void read(int &x)
    {
        x=0;
        int f=1;
        char c=getchar();
        while('0'>c||c>'9')
        {
            if(c=='-')
                f=-1;
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        x*=f;
    }
    void read(long long &x)
    {
        x=0;
        int f=1;
        char c=getchar();
        while('0'>c||c>'9')
        {
            if(c=='-')
                f=-1;
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        x*=f;
    }
    void write(int x)
    {
        if(x>9)
            write(x/10);
        putchar(x%10+'0');
    }
    void write(long long x)
    {
        if(x>9)
            write(x/10);
        putchar(x%10+'0');
    }
}
using namespace IO;
struct node
{
    int e;
    int w,c;
};
struct node_set
{
    int s;
    int len;
    friend bool operator < (const node_set &a,const node_set &b)
    {
        return 1ll*a.s*a.len>1ll*b.s*b.len;
    }
};
int T;
int n,cnt;
int w;
long long s;
long long now;
vector<node> g[100005];
int st[100005],ed[100005];
multiset<node_set> t[3];
void init()
{
    w=0;now=0;cnt=0;
    t[1].clear();t[2].clear();
    for(int i=1;i<=n;i++)
        g[i].clear();
}
void dfs(int u,int fa)
{
    if(g[u].size()==1&&g[u].back().e==fa)
    {
        cnt++;
		st[u]=cnt;
	}
	else
		st[u]=(1ll<<30);

	for(int i=0;i<g[u].size();i++)
    {
        int v=g[u][i].e;
        if(v!=fa)
        {
            dfs(v,u);
            st[u]=min(st[u],st[v]);
            t[g[u][i].c].insert((node_set){g[u][i].w,ed[v]-st[v]+1});
            now=now+1ll*g[u][i].w*(ed[v]-st[v]+1);
        }
    }
    ed[u]=cnt;
}
void c_in()
{
    cin>>n>>s;
    init();
    for(int i=1;i<n;i++)
    {
        int u,v,w,c;
        read(u);read(v);
        read(w);read(c);
        g[u].push_back((node){v,w,c});g[v].push_back((node){u,w,c});
    }
    dfs(1,0);
    //cout<<"now:"<<now<<'\n';
    if(now<=s)
    {
        write(0);
        putchar('\n');
        return;
    }
    if(t[2].size()==0)
    {
        if(T==200)
        cout<<"opt1:";
        while(now>s)
        {
            node_set temp=(*t[1].begin());t[1].erase(temp);
            t[1].insert((node_set){temp.s/2,temp.len});
            now=now-(1ll*temp.s*temp.len-(1ll*temp.s)/2*temp.len);
            w++;
        }
        write(w);
        putchar('\n');
        return;
    }
    if(t[1].size()==0)
    {
        if(T==200)
        cout<<"opt2:";
        while(now>s)
        {
            node_set temp=(*t[2].begin());t[2].erase(temp);
            t[2].insert((node_set){temp.s/2,temp.len});
            now=now-(1ll*temp.s*temp.len-(1ll*temp.s)/2*temp.len);
            w+=2;
        }
        write(w);
        putchar('\n');
        return;
    }
    if(T==200)
    cout<<"opt3:";
    while(1)
    {
        node_set temp1,temp2,temp3;
        temp1=(*t[1].begin());t[1].erase(temp1);
        t[1].insert((node_set){temp1.s/2,temp1.len});

        temp2=(*t[1].begin());t[1].erase(temp2);
        t[1].insert((node_set){temp2.s/2,temp2.len});

        temp3=(*t[2].begin());t[2].erase(temp3);
        t[2].insert((node_set){temp3.s/2,temp3.len});
        if(now-1ll*temp1.s*temp1.len<=s)
        {
            w++;
            break;
        }
        w+=2;
        if(1ll*temp1.s*temp1.len+1ll*temp2.s*temp2.len-(1ll*temp1.s/2)*temp1.len-(1ll*temp2.s/2)*temp2.len<1ll*temp3.s*temp3.len-(1ll*temp3.s/2)*temp3.len)
        {
        	now=now-(1ll*temp3.s*temp3.len-(1ll*temp3.s/2)*temp3.len);
            t[1].erase((node_set){temp1.s/2,temp1.len});t[1].erase((node_set){temp2.s/2,temp2.len});
            t[1].insert(temp1);t[1].insert(temp2);
        }
        else
        {
        	now=now-(1ll*temp1.s*temp1.len+1ll*temp2.s*temp2.len-(1ll*temp1.s/2)*temp1.len-(1ll*temp2.s/2)*temp2.len);
            t[2].erase((node_set){temp3.s/2,temp3.len});
            t[2].insert(temp3);
        }
    }
    write(w);
    putchar('\n');
}
int main()
{
    cin>>T;
    for(int i=1;i<=T;i++)
        c_in();
    return 0;
}
/*
200
10 120
3 1 8 1
5 2 10 1
8 1 5 1
2 1 6 1
7 2 8 1
10 7 7 1
6 4 10 1
4 3 10 1
9 7 9 1
10 97
3 1 1 1
5 1 9 1
6 3 6 1
4 3 5 1
2 1 4 1
7 6 10 1
10 6 8 1
9 8 3 1
8 5 1 1
10 119
5 4 9 1
10 8 1 1
4 3 10 1
6 5 1 1
3 2 1 1
8 7 7 1
2 1 2 1
9 7 4 1
7 6 9 1
10 28
8 2 8 1
5 1 4 1
6 1 10 1
10 2 7 1
7 2 1 1
9 2 1 1
2 1 5 1
4 1 9 1
3 2 5 1
*/


#include<iostream>
#include<cstdio>
#include<vector>
#include<set>
using namespace std;
#define pii pair<int,int>
#define x first
#define y second
namespace IO
{
    void read(int &x)
    {
        x=0;
        int f=1;
        char c=getchar();
        while('0'>c||c>'9')
        {
            if(c=='-')
                f=-1;
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        x*=f;
    }
    void read(long long &x)
    {
        x=0;
        int f=1;
        char c=getchar();
        while('0'>c||c>'9')
        {
            if(c=='-')
                f=-1;
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        x*=f;
    }
    void write(int x)
    {
        if(x>9)
            write(x/10);
        putchar(x%10+'0');
    }
    void write(long long x)
    {
        if(x>9)
            write(x/10);
        putchar(x%10+'0');
    }
}
using namespace IO;
struct node
{
    int e;
    int w,c;
};
struct node_set
{
    int s;
    int len;
    friend bool operator < (const node_set &a,const node_set &b)
    {
        return 1ll*a.s*a.len>1ll*b.s*b.len;
    }
};
int T;
int n,cnt;
int w;
long long s;
long long now;
vector<node> g[100005];
int st[100005],ed[100005];
multiset<node_set> t[3];
void init()
{
    w=0;now=0;cnt=0;
    t[1].clear();t[2].clear();
    for(int i=1;i<=n;i++)
        g[i].clear();
}
void dfs(int u,int fa)
{
    if(g[u].size()==1&&g[u].back().e==fa)
    {
        cnt++;
		st[u]=cnt;
	}
	else
		st[u]=(1ll<<30);

	for(int i=0;i<g[u].size();i++)
    {
        int v=g[u][i].e;
        if(v!=fa)
        {
            dfs(v,u);
            st[u]=min(st[u],st[v]);
            t[g[u][i].c].insert((node_set){g[u][i].w,ed[v]-st[v]+1});
            now=now+1ll*g[u][i].w*(ed[v]-st[v]+1);
        }
    }
    ed[u]=cnt;
}
void c_in()
{
    cin>>n>>s;
    init();
    for(int i=1;i<n;i++)
    {
        int u,v,w,c;
        read(u);read(v);
        read(w);read(c);
        g[u].push_back((node){v,w,c});g[v].push_back((node){u,w,c});
    }
    dfs(1,0);
    //cout<<"now:"<<now<<'\n';
    if(now<=s)
    {
        write(0);
        putchar('\n');
        return;
    }
    if(t[2].size()==0)
    {
        while(now>s)
        {
            node_set temp=(*t[1].begin());t[1].erase(temp);
            t[1].insert((node_set){temp.s/2,temp.len});
            now=now-(1ll*temp.s*temp.len-(1ll*temp.s)/2*temp.len);
            w++;
        }
        write(w);
        putchar('\n');
        return;
    }
    if(t[1].size()==0)
    {
        while(now>s)
        {
            node_set temp=(*t[2].begin());t[2].erase(temp);
            t[2].insert((node_set){temp.s/2,temp.len});
            now=now-(1ll*temp.s*temp.len-(1ll*temp.s)/2*temp.len);
            w+=2;
        }
        write(w);
        putchar('\n');
        return;
    }
    while(1)
    {
        node_set temp1,temp2,temp3;
        temp1=(*t[1].begin());t[1].erase(temp1);
        t[1].insert((node_set){temp1.s/2,temp1.len});

        temp2=(*t[1].begin());t[1].erase(temp2);
        t[1].insert((node_set){temp2.s/2,temp2.len});

        temp3=(*t[2].begin());t[2].erase(temp3);
        t[2].insert((node_set){temp3.s/2,temp3.len});
        if(now-1ll*temp1.s*temp1.len<=s)
        {
            w++;
            break;
        }
        w+=2;
        if(1ll*temp1.s*temp1.len+1ll*temp2.s*temp2.len-(1ll*temp1.s/2)*temp1.len-(1ll*temp2.s/2)*temp2.len<1ll*temp3.s*temp3.len-(1ll*temp3.s/2)*temp3.len)
        {
        	now=now-(1ll*temp3.s*temp3.len-(1ll*temp3.s/2)*temp3.len);
            t[1].erase((node_set){temp1.s/2,temp1.len});t[1].erase((node_set){temp2.s/2,temp2.len});
            t[1].insert(temp1);t[1].insert(temp2);
        }
        else
        {
        	now=now-(1ll*temp1.s*temp1.len+1ll*temp2.s*temp2.len-(1ll*temp1.s/2)*temp1.len-(1ll*temp2.s/2)*temp2.len);
            t[2].erase((node_set){temp3.s/2,temp3.len});
            t[2].insert(temp3);
        }
    }
    write(w);
    putchar('\n');
}
int main()
{
    cin>>T;
    for(int i=1;i<=T;i++)
        c_in();
    return 0;
}
/*
200
10 120
3 1 8 1
5 2 10 1
8 1 5 1
2 1 6 1
7 2 8 1
10 7 7 1
6 4 10 1
4 3 10 1
9 7 9 1
10 97
3 1 1 1
5 1 9 1
6 3 6 1
4 3 5 1
2 1 4 1
7 6 10 1
10 6 8 1
9 8 3 1
8 5 1 1
10 119
5 4 9 1
10 8 1 1
4 3 10 1
6 5 1 1
3 2 1 1
8 7 7 1
2 1 2 1
9 7 4 1
7 6 9 1
10 28
8 2 8 1
5 1 4 1
6 1 10 1
10 2 7 1
7 2 1 1
9 2 1 1
2 1 5 1
4 1 9 1
3 2 5 1
*/


#include<iostream>
#include<cstdio>
#include<vector>
#include<set>
using namespace std;
#define pii pair<int,int>
#define x first
#define y second
namespace IO
{
    void read(int &x)
    {
        x=0;
        int f=1;
        char c=getchar();
        while('0'>c||c>'9')
        {
            if(c=='-')
                f=-1;
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        x*=f;
    }
    void read(long long &x)
    {
        x=0;
        int f=1;
        char c=getchar();
        while('0'>c||c>'9')
        {
            if(c=='-')
                f=-1;
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        x*=f;
    }
    void write(int x)
    {
        if(x>9)
            write(x/10);
        putchar(x%10+'0');
    }
    void write(long long x)
    {
        if(x>9)
            write(x/10);
        putchar(x%10+'0');
    }
}
using namespace IO;
struct node
{
    int e;
    int w,c;
};
struct node_set
{
    int s;
    int len;
    friend bool operator < (const node_set &a,const node_set &b)
    {
        return 1ll*a.s*a.len>1ll*b.s*b.len;
    }
};
int T;
int n,cnt;
int w;
long long s;
long long now;
vector<node> g[100005];
int st[100005],ed[100005];
multiset<node_set> t[3];
void init()
{
    w=0;now=0;cnt=0;
    t[1].clear();t[2].clear();
    for(int i=1;i<=n;i++)
        g[i].clear();
}
void dfs(int u,int fa)
{
    if(g[u].size()==1&&g[u].back().e==fa)
    {
        cnt++;
		st[u]=cnt;
	}
	else
		st[u]=(1ll<<30);

	for(int i=0;i<g[u].size();i++)
    {
        int v=g[u][i].e;
        if(v!=fa)
        {
            dfs(v,u);
            st[u]=min(st[u],st[v]);
            t[g[u][i].c].insert((node_set){g[u][i].w,ed[v]-st[v]+1});
            now=now+1ll*g[u][i].w*(ed[v]-st[v]+1);
        }
    }
    ed[u]=cnt;
}
void c_in()
{
    cin>>n>>s;
    init();
    for(int i=1;i<n;i++)
    {
        int u,v,w,c;
        read(u);read(v);
        read(w);read(c);
        g[u].push_back((node){v,w,c});g[v].push_back((node){u,w,c});
    }
    dfs(1,0);
    if(now<=s)
    {
        write(0);
        putchar('\n');
        return;
    }
    if(t[2].size()==0)
    {
        while(now>s)
        {
            node_set temp=(*t[1].begin());t[1].erase(temp);
            t[1].insert((node_set){temp.s/2,temp.len});
            now=now-(1ll*temp.s*temp.len-(1ll*temp.s)/2*temp.len);
            w++;
        }
        write(w);
        putchar('\n');
        return;
    }
    if(t[1].size()==0)
    {
        while(now>s)
        {
            node_set temp=(*t[2].begin());t[2].erase(temp);
            t[2].insert((node_set){temp.s/2,temp.len});
            now=now-(1ll*temp.s*temp.len-(1ll*temp.s)/2*temp.len);
            w+=2;
        }
        write(w);
        putchar('\n');
        return;
    }
    while(now>s)
    {
        node_set temp1,temp2,temp3;
        temp1=(*t[1].begin());t[1].erase(temp1);
        t[1].insert((node_set){temp1.s/2,temp1.len});

        temp2=(*t[1].begin());t[1].erase(temp2);
        t[1].insert((node_set){temp2.s/2,temp2.len});

        temp3=(*t[2].begin());t[2].erase(temp3);
        t[2].insert((node_set){temp3.s/2,temp3.len});

        if(now-(1ll*temp1.s*temp1.len-(1ll*temp1.s/2)*temp1.len)<=s)
        {
            w++;
            break;
        }
        if(now-(1ll*temp1.s*temp1.len-(1ll*temp1.s/2)*temp1.len)-(1ll*temp3.s*temp3.len-(1ll*temp3.s/2)*temp3.len)<=s)
        {
        	w+=3;
        	break;
		}
        w+=2;
        if(1ll*temp1.s*temp1.len+1ll*temp2.s*temp2.len-(1ll*temp1.s/2)*temp1.len-(1ll*temp2.s/2)*temp2.len<=1ll*temp3.s*temp3.len-(1ll*temp3.s/2)*temp3.len)
        {
        	now=now-(1ll*temp3.s*temp3.len-(1ll*temp3.s/2)*temp3.len);
            t[1].erase((node_set){temp1.s/2,temp1.len});t[1].erase((node_set){temp2.s/2,temp2.len});
            t[1].insert(temp1);t[1].insert(temp2);
        }
        else
        {
        	now=now-(1ll*temp1.s*temp1.len+1ll*temp2.s*temp2.len-(1ll*temp1.s/2)*temp1.len-(1ll*temp2.s/2)*temp2.len);
            t[2].erase((node_set){temp3.s/2,temp3.len});
            t[2].insert(temp3);
        }
    }
    write(w);
    putchar('\n');
}
int main()
{
    cin>>T;
    for(int i=1;i<=T;i++)
        c_in();
    return 0;
}
/*
1
10 19158
1 2 15661 1
1 3 7460 1
2 4 8989 2
1 5 1602 2
2 6 19664 2
3 7 5276 1
5 8 24070 1
5 9 17520 2
2 10 28763 2
*/


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<set>
using namespace std;
#define pii pair<int,int>
#define x first
#define y second
namespace IO
{
    void read(int &x)
    {
        x=0;
        int f=1;
        char c=getchar();
        while('0'>c||c>'9')
        {
            if(c=='-')
                f=-1;
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        x*=f;
    }
    void read(long long &x)
    {
        x=0;
        int f=1;
        char c=getchar();
        while('0'>c||c>'9')
        {
            if(c=='-')
                f=-1;
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        x*=f;
    }
    void write(int x)
    {
        if(x>9)
            write(x/10);
        putchar(x%10+'0');
    }
    void write(long long x)
    {
        if(x>9)
            write(x/10);
        putchar(x%10+'0');
    }
}
using namespace IO;
struct node
{
    int e;
    int w,c;
};
struct node_set
{
    int s;
    int len;
    friend bool operator < (const node_set &a,const node_set &b)
    {
        return (1ll*a.s*a.len)-((1ll*a.s/2)*a.len)>(1ll*b.s*b.len)-((1ll*b.s/2)*b.len);
    }
};
int T;
int n,cnt;
int w;
long long s;
long long now;
vector<node> g[100005];
int st[100005],ed[100005];
vector<node_set> t[3];
long long pre[100005];
void init()
{
    w=(1ll<<30);now=0;cnt=0;
    t[1].clear();t[2].clear();
    for(int i=1;i<=n;i++)
        g[i].clear();
}
void dfs(int u,int fa)
{
    if(g[u].size()==1&&g[u].back().e==fa)
    {
        cnt++;
		st[u]=cnt;
	}
	else
		st[u]=(1ll<<30);

	for(int i=0;i<g[u].size();i++)
    {
        int v=g[u][i].e;
        if(v!=fa)
        {
            dfs(v,u);
            st[u]=min(st[u],st[v]);
            t[g[u][i].c].push_back((node_set){g[u][i].w,ed[v]-st[v]+1});
            now=now+1ll*g[u][i].w*(ed[v]-st[v]+1);
        }
    }
    ed[u]=cnt;
}
int check(long long now)
{
	if(t[2].size()==0)
		return (1ll<<30);
    int l=0,r=t[2].size()-1,mid;
	if(now-pre[r]>s)
		return (1ll<<30);
    while(l+1<r)
    {
        mid=(l+r)>>1;
        if(now-pre[mid]<=s)
            r=mid;
        else
            l=mid;
    }
    while(now-pre[r-1]<=s)
        r--;
    return (r+1)*2;
}
void c_in()
{
    cin>>n>>s;
    init();
    for(int i=1;i<n;i++)
    {
        int u,v,w,c;
        read(u);read(v);
        read(w);read(c);
        g[u].push_back((node){v,w,c});g[v].push_back((node){u,w,c});
    }
    dfs(1,0);
    if(now<=s)
    {
    	write(0);
    	putchar('\n');
    	return;
	}
    int len1=t[1].size(),len2=t[2].size();
    for(int i=0;i<len1;i++)
    {
        int now=t[1][i].s;
        while(now/2)
        {
            now/=2;
            t[1].push_back((node_set){now,t[1][i].len});
        }
    }
    for(int i=0;i<len2;i++)
    {
        int now=t[2][i].s;
        while(now)
        {
            now/=2;
            t[2].push_back((node_set){now,t[2][i].len});
        }
    }
    sort(t[1].begin(),t[1].end());sort(t[2].begin(),t[2].end());
    if(t[2].size())
    {
    	pre[0]=1ll*t[2][0].s*t[2][0].len-(1ll*t[2][0].s/2)*t[2][0].len;
    	for(int i=1;i<t[2].size();i++)
         	pre[i]=pre[i-1]+(1ll*t[2][i].s*t[2][i].len-(1ll*t[2][i].s/2)*t[2][i].len);
	}
    w=check(now);
	for(int i=0;i<t[1].size();i++)
    {
        now=now-(1ll*t[1][i].s*t[1][i].len-(1ll*t[1][i].s/2)*t[1][i].len);
        if(now<=s)
        {
            w=min(w,i+1);
            break;
        }
        w=min(w,i+1+check(now));
    }
    write(w);putchar('\n');
}
int main()
{
    cin>>T;
    for(int i=1;i<=T;i++)
        c_in();
    return 0;
}
/*
1
10 28
8 2 8 1
5 1 4 1
6 1 10 1
10 2 7 1
7 2 1 1
9 2 1 1
2 1 5 1
4 1 9 1
3 2 5 1
*/


#include<iostream>
#include<cstdio>
#include<vector>
#include<set>
using namespace std;
#define pii pair<int,int>
#define x first
#define y second
namespace IO
{
    void read(int &x)
    {
        x=0;
        int f=1;
        char c=getchar();
        while('0'>c||c>'9')
        {
            if(c=='-')
                f=-1;
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        x*=f;
    }
    void read(long long &x)
    {
        x=0;
        int f=1;
        char c=getchar();
        while('0'>c||c>'9')
        {
            if(c=='-')
                f=-1;
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        x*=f;
    }
    void write(int x)
    {
        if(x>9)
            write(x/10);
        putchar(x%10+'0');
    }
    void write(long long x)
    {
        if(x>9)
            write(x/10);
        putchar(x%10+'0');
    }
}
using namespace IO;
struct node
{
    int e;
    int w,c;
};
struct node_set
{
    int s;
    int len;
    friend bool operator < (const node_set &a,const node_set &b)
    {
        return 1ll*a.s*a.len>1ll*b.s*b.len;
    }
};
int T;
int n,cnt;
int w;
long long s;
long long now;
vector<node> g[100005];
int st[100005],ed[100005];
multiset<node_set> t[3];
void init()
{
    w=0;now=0;cnt=0;
    t[1].clear();t[2].clear();
    for(int i=1;i<=n;i++)
        g[i].clear();
}
void dfs(int u,int fa)
{
    if(g[u].size()==1&&g[u].back().e==fa)
    {
        cnt++;
		st[u]=cnt;
	}
	else
		st[u]=(1ll<<30);

	for(int i=0;i<g[u].size();i++)
    {
        int v=g[u][i].e;
        if(v!=fa)
        {
            dfs(v,u);
            st[u]=min(st[u],st[v]);
            t[g[u][i].c].insert((node_set){g[u][i].w,ed[v]-st[v]+1});
            now=now+1ll*g[u][i].w*(ed[v]-st[v]+1);
        }
    }
    ed[u]=cnt;
}
void c_in()
{
    cin>>n>>s;
    init();
    for(int i=1;i<n;i++)
    {
        int u,v,w,c;
        read(u);read(v);
        read(w);read(c);
        g[u].push_back((node){v,w,c});g[v].push_back((node){u,w,c});
    }
    if(T==200)
        cout<<"be ";
    dfs(1,0);
    if(T==200)
        cout<<"ed\n";
    //cout<<"now:"<<now<<'\n';
    if(now<=s)
    {
        write(0);
        putchar('\n');
        return;
    }
    if(t[2].size()==0)
    {
        if(T==200)
        cout<<"opt1:";
        while(now>s)
        {
            node_set temp=(*t[1].begin());t[1].erase(temp);
            t[1].insert((node_set){temp.s/2,temp.len});
            now=now-(1ll*temp.s*temp.len-(1ll*temp.s)/2*temp.len);
            w++;
        }
        write(w);
        putchar('\n');
        return;
    }
    if(t[1].size()==0)
    {
        if(T==200)
        cout<<"opt2:";
        while(now>s)
        {
            node_set temp=(*t[2].begin());t[2].erase(temp);
            t[2].insert((node_set){temp.s/2,temp.len});
            now=now-(1ll*temp.s*temp.len-(1ll*temp.s)/2*temp.len);
            w+=2;
        }
        write(w);
        putchar('\n');
        return;
    }
    if(T==200)
    cout<<"opt3:";
    while(1)
    {
        node_set temp1,temp2,temp3;
        temp1=(*t[1].begin());t[1].erase(temp1);
        t[1].insert((node_set){temp1.s/2,temp1.len});

        temp2=(*t[1].begin());t[1].erase(temp2);
        t[1].insert((node_set){temp2.s/2,temp2.len});

        temp3=(*t[2].begin());t[2].erase(temp3);
        t[2].insert((node_set){temp3.s/2,temp3.len});
        if(now-1ll*temp1.s*temp1.len<=s)
        {
            w++;
            break;
        }
        w+=2;
        if(1ll*temp1.s*temp1.len+1ll*temp2.s*temp2.len-(1ll*temp1.s/2)*temp1.len-(1ll*temp2.s/2)*temp2.len<1ll*temp3.s*temp3.len-(1ll*temp3.s/2)*temp3.len)
        {
        	now=now-(1ll*temp3.s*temp3.len-(1ll*temp3.s/2)*temp3.len);
            t[1].erase((node_set){temp1.s/2,temp1.len});t[1].erase((node_set){temp2.s/2,temp2.len});
            t[1].insert(temp1);t[1].insert(temp2);
        }
        else
        {
        	now=now-(1ll*temp1.s*temp1.len+1ll*temp2.s*temp2.len-(1ll*temp1.s/2)*temp1.len-(1ll*temp2.s/2)*temp2.len);
            t[2].erase((node_set){temp3.s/2,temp3.len});
            t[2].insert(temp3);
        }
    }
    write(w);
    putchar('\n');
}
int main()
{
    cin>>T;
    for(int i=1;i<=T;i++)
        c_in();
    return 0;
}
/*
200
10 120
3 1 8 1
5 2 10 1
8 1 5 1
2 1 6 1
7 2 8 1
10 7 7 1
6 4 10 1
4 3 10 1
9 7 9 1
10 97
3 1 1 1
5 1 9 1
6 3 6 1
4 3 5 1
2 1 4 1
7 6 10 1
10 6 8 1
9 8 3 1
8 5 1 1
10 119
5 4 9 1
10 8 1 1
4 3 10 1
6 5 1 1
3 2 1 1
8 7 7 1
2 1 2 1
9 7 4 1
7 6 9 1
10 28
8 2 8 1
5 1 4 1
6 1 10 1
10 2 7 1
7 2 1 1
9 2 1 1
2 1 5 1
4 1 9 1
3 2 5 1
*/


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<set>
using namespace std;
#define pii pair<int,int>
#define x first
#define y second
namespace IO
{
    void read(int &x)
    {
        x=0;
        int f=1;
        char c=getchar();
        while('0'>c||c>'9')
        {
            if(c=='-')
                f=-1;
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        x*=f;
    }
    void read(long long &x)
    {
        x=0;
        int f=1;
        char c=getchar();
        while('0'>c||c>'9')
        {
            if(c=='-')
                f=-1;
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        x*=f;
    }
    void write(int x)
    {
        if(x>9)
            write(x/10);
        putchar(x%10+'0');
    }
    void write(long long x)
    {
        if(x>9)
            write(x/10);
        putchar(x%10+'0');
    }
}
using namespace IO;
struct node
{
    int e;
    int w,c;
};
struct node_set
{
    int s;
    int len;
    friend bool operator < (const node_set &a,const node_set &b)
    {
        return (1ll*a.s*a.len)-((1ll*a.s/2)*a.len)>(1ll*b.s*b.len)-((1ll*b.s/2)*b.len);
    }
};
int T;
int n,cnt;
int w;
long long s;
long long now;
vector<node> g[100005];
int st[100005],ed[100005];
vector<node_set> t[3];
long long pre[100005*30];
void init()
{
    w=(1ll<<30);now=0;cnt=0;
    t[1].clear();t[2].clear();
    for(int i=1;i<=n;i++)
        g[i].clear();
}
void dfs(int u,int fa)
{
    if(g[u].size()==1&&g[u].back().e==fa)
    {
        cnt++;
		st[u]=cnt;
	}
	else
		st[u]=(1ll<<30);

	for(int i=0;i<g[u].size();i++)
    {
        int v=g[u][i].e;
        if(v!=fa)
        {
            dfs(v,u);
            st[u]=min(st[u],st[v]);
            t[g[u][i].c].push_back((node_set){g[u][i].w,ed[v]-st[v]+1});
            now=now+1ll*g[u][i].w*(ed[v]-st[v]+1);
        }
    }
    ed[u]=cnt;
}
int check(long long now)
{
	if(t[2].size()==0)
		return (1ll<<30);
    int l=0,r=t[2].size()-1,mid;
	if(now-pre[r]>s)
		return (1ll<<30);
    while(l+1<r)
    {
        mid=(l+r)>>1;
        if(now-pre[mid]<=s)
            r=mid;
        else
            l=mid;
    }
    while(now-pre[r-1]<=s)
        r--;
    return (r+1)*2;
}
void c_in()
{
    cin>>n>>s;
    init();
    for(int i=1;i<n;i++)
    {
        int u,v,w,c;
        read(u);read(v);
        read(w);read(c);
        g[u].push_back((node){v,w,c});g[v].push_back((node){u,w,c});
    }
    dfs(1,0);
    if(now<=s)
    {
    	write(0);
    	putchar('\n');
    	return;
	}
    int len1=t[1].size(),len2=t[2].size();
    for(int i=0;i<len1;i++)
    {
        int now=t[1][i].s;
        while(now/2)
        {
            now/=2;
            t[1].push_back((node_set){now,t[1][i].len});
        }
    }
    for(int i=0;i<len2;i++)
    {
        int now=t[2][i].s;
        while(now)
        {
            now/=2;
            t[2].push_back((node_set){now,t[2][i].len});
        }
    }
    sort(t[1].begin(),t[1].end());sort(t[2].begin(),t[2].end());
    if(t[2].size())
    {
    	pre[0]=1ll*t[2][0].s*t[2][0].len-(1ll*t[2][0].s/2)*t[2][0].len;
    	for(int i=1;i<t[2].size();i++)
         	pre[i]=pre[i-1]+(1ll*t[2][i].s*t[2][i].len-(1ll*t[2][i].s/2)*t[2][i].len);
	}
    w=check(now);
	for(int i=0;i<t[1].size();i++)
    {
        now=now-(1ll*t[1][i].s*t[1][i].len-(1ll*t[1][i].s/2)*t[1][i].len);
        if(now<=s)
        {
            w=min(w,i+1);
            break;
        }
        w=min(w,i+1+check(now));
    }
    write(w);putchar('\n');
}
int main()
{
    cin>>T;
    for(int i=1;i<=T;i++)
        c_in();
    return 0;
}
/*
1
10 28
8 2 8 1
5 1 4 1
6 1 10 1
10 2 7 1
7 2 1 1
9 2 1 1
2 1 5 1
4 1 9 1
3 2 5 1
*/


#include <bits/stdc++.h>

#define ll long long int

using namespace std;

const int N = 1e5 + 7;
int n, vis[N];
vector < pair <int, int> > adj[N], edges;
ll s, tot1, tot2;
struct cmp {
    bool operator()(pair <ll, ll> a, pair <ll, ll> b) {
        double a_diff = double(edges[a.first].first - edges[a.first].first/2)*a.second;
        double b_diff = double(edges[b.first].first - edges[b.first].first/2)*b.second;
        return a_diff < b_diff;
    }
};
priority_queue <pair <ll, ll> , vector < pair <ll, ll> >, cmp> pq1, pq2;

int dfs(int v) {
    vis[v] = 1;
    int cnt = 0;
    for (auto u: adj[v]) {
        if (!vis[u.first]) {
            int ret = dfs(u.first);
            cnt += ret;
            //cout << edges[u.second].first << ": " << ret << endl;
            if (edges[u.second].second == 1) {
                tot1 += 1ll*edges[u.second].first*ret;
                pq1.push({u.second, 1ll*ret});
            }
            else {
                tot2 += 1ll*edges[u.second].first*ret;
                pq2.push({u.second, 1ll*ret});
            }
        }
    }

    return max(1, cnt);
}

int main() {
    int t;
    cin >> t;
    while (t--) {
        cin >> n >> s;
        for (int i=0; i<=n; i++) adj[i].clear();
        edges.clear();
        tot1 = tot2 = 0;
        memset(vis, 0, sizeof(vis));
        while (!pq1.empty()) pq1.pop();
        while (!pq2.empty()) pq2.pop();
        for (int i=0; i<n-1; i++) {
            int u, v, w, c;
            cin >> u >> v >> w >> c;
            edges.push_back({w, c});
            adj[u].push_back({v, edges.size()-1});
            adj[v].push_back({u, edges.size()-1});
        }
        dfs(1);
        vector <int> diff1, diff2;
        diff1.push_back(tot1);
        diff2.push_back(tot2);
        while (tot1 && !pq1.empty()) {
            pair <ll, ll> val = pq1.top();
            pq1.pop();
            //cout << val.first << ": " << edges[val.first].first << " " << edges[val.first].second << endl;
            tot1 = tot1 - edges[val.first].first*val.second + (edges[val.first].first/2)*val.second;
            diff1.push_back(tot1);
            edges[val.first].first /= 2;
            if (edges[val.first].first) pq1.push({val.first, val.second});
        }
        while (tot2 && !pq2.empty()) {
            pair <ll, ll> val = pq2.top();
            pq2.pop();
            //cout << val.first << ": " << edges[val.first].first << " " << edges[val.first].second << endl;
            tot2 = tot2 - edges[val.first].first*val.second + (edges[val.first].first/2)*val.second;
            diff2.push_back(tot2);
            edges[val.first].first /= 2;
            if (edges[val.first].first) pq2.push({val.first, val.second});
        }
        int res = (diff1.size() - 1) + 2*(diff2.size() - 1);
        int i, j;
        //for (i=0; i<diff1.size(); i++) cout << diff1[i] << " ";
        //cout << endl;
        //for (i=0; i<diff2.size(); i++) cout << diff2[i] << " ";
        //cout << endl;
        for (i=0, j=diff2.size()-1; i<diff1.size() && j>=0; ) {
            //cout << i << ", " << j << ": " << res << endl;
            if (diff1[i] + diff2[j] <= s) {
                res = min(res, i + 2*j);
                j--;
            }
            else i++;
        }
        cout << res << endl;
    }

    return 0;
}


#include <bits/stdc++.h>

#define ll long long int

using namespace std;

const int N = 1e5 + 7;
int n, vis[N];
vector < pair <int, int> > adj[N], edges;
ll s, tot1, tot2;
struct cmp {
    bool operator()(pair <ll, ll> a, pair <ll, ll> b) {
        double a_diff = double(edges[a.first].first - edges[a.first].first/2)*a.second;
        double b_diff = double(edges[b.first].first - edges[b.first].first/2)*b.second;
        return a_diff < b_diff;
    }
};
priority_queue <pair <ll, ll> , vector < pair <ll, ll> >, cmp> pq1, pq2;

int dfs(int v) {
    vis[v] = 1;
    int cnt = 0;
    for (auto u: adj[v]) {
        if (!vis[u.first]) {
            int ret = dfs(u.first);
            cnt += ret;
            //cout << edges[u.second].first << ": " << ret << endl;
            if (edges[u.second].second == 1) {
                tot1 += 1ll*edges[u.second].first*ret;
                pq1.push({u.second, 1ll*ret});
            }
            else {
                tot2 += 1ll*edges[u.second].first*ret;
                pq2.push({u.second, 1ll*ret});
            }
        }
    }

    return max(1, cnt);
}

int main() {
    int t;
    cin >> t;
    while (t--) {
        cin >> n >> s;
        for (int i=0; i<=n; i++) adj[i].clear();
        edges.clear();
        tot1 = tot2 = 0;
        memset(vis, 0, sizeof(vis));
        while (!pq1.empty()) pq1.pop();
        while (!pq2.empty()) pq2.pop();
        for (int i=0; i<n-1; i++) {
            int u, v, w, c;
            cin >> u >> v >> w >> c;
            edges.push_back({w, c});
            adj[u].push_back({v, edges.size()-1});
            adj[v].push_back({u, edges.size()-1});
        }
        dfs(1);
        vector <ll> diff1, diff2;
        diff1.push_back(tot1);
        diff2.push_back(tot2);
        while (tot1 && !pq1.empty()) {
            pair <ll, ll> val = pq1.top();
            pq1.pop();
            //cout << val.first << ": " << edges[val.first].first << " " << edges[val.first].second << endl;
            tot1 = tot1 - edges[val.first].first*val.second + (edges[val.first].first/2)*val.second;
            diff1.push_back(tot1);
            edges[val.first].first /= 2;
            if (edges[val.first].first) pq1.push({val.first, val.second});
        }
        while (tot2 && !pq2.empty()) {
            pair <ll, ll> val = pq2.top();
            pq2.pop();
            //cout << val.first << ": " << edges[val.first].first << " " << edges[val.first].second << endl;
            tot2 = tot2 - edges[val.first].first*val.second + (edges[val.first].first/2)*val.second;
            diff2.push_back(tot2);
            edges[val.first].first /= 2;
            if (edges[val.first].first) pq2.push({val.first, val.second});
        }
        int res = (diff1.size() - 1) + 2*(diff2.size() - 1);
        int i, j;
        //for (i=0; i<diff1.size(); i++) cout << diff1[i] << " ";
        //cout << endl;
        //for (i=0; i<diff2.size(); i++) cout << diff2[i] << " ";
        //cout << endl;
        for (i=0, j=diff2.size()-1; i<diff1.size() && j>=0; ) {
            //cout << i << ", " << j << ": " << res << endl;
            if (diff1[i] + diff2[j] <= s) {
                res = min(res, i + 2*j);
                j--;
            }
            else i++;
        }
        cout << res << endl;
    }

    return 0;
}


#include <bits/stdc++.h>

#define ll long long int

using namespace std;

const int N = 1e5 + 7;
int n, vis[N];
vector < pair <int, int> > adj[N], edges;
ll s, tot;
struct cmp {
    bool operator()(pair <ll, ll> a, pair <ll, ll> b) {
        return double(edges[a.first].first - edges[a.first].first/2)*a.second/double(edges[a.first].second) < double(edges[b.first].first - edges[b.first].first/2)*b.second/double(edges[b.first].second);
    }
};
priority_queue <pair <ll, ll> , vector < pair <ll, ll> >, cmp> pq;

int dfs(int v) {
    vis[v] = 1;
    int cnt = 0;
    for (auto u: adj[v]) {
        if (!vis[u.first]) {
            int ret = dfs(u.first);
            cnt += ret;
            //cout << edges[u.second].first << ": " << ret << endl;
            tot += 1ll*edges[u.second].first*ret;
            pq.push({u.second, 1ll*ret});
        }
    }

    return max(1, cnt);
}

int main() {
    int t;
    cin >> t;
    while (t--) {
        cin >> n >> s;
        for (int i=0; i<=n; i++) adj[i].clear();
        edges.clear();
        tot = 0;
        memset(vis, 0, sizeof(vis));
        while (!pq.empty()) pq.pop();
        for (int i=0; i<n-1; i++) {
            int u, v, w, c;
            cin >> u >> v >> w >> c;
            edges.push_back({w, c});
            adj[u].push_back({v, edges.size()-1});
            adj[v].push_back({u, edges.size()-1});
        }
        dfs(1);
        ll res = 0;
        while (tot > s && !pq.empty()) {
            pair <ll, ll> val = pq.top();
            pq.pop();
            //cout << val.first << ": " << edges[val.first].first << " " << edges[val.first].second << endl;
            tot = tot - edges[val.first].first*val.second + (edges[val.first].first/2)*val.second;
            edges[val.first].first /= 2;
            if (edges[val.first].first) pq.push({val.first, val.second});
            res += edges[val.first].second;
        }
        cout << res << endl;
    }

    return 0;
}


#include <bits/stdc++.h>

#define ll long long int

using namespace std;

const int N = 1e5 + 7;
int n, vis[N];
vector < pair <int, int> > adj[N], edges;
ll s, tot;
struct cmp {
    bool operator()(pair <ll, ll> a, pair <ll, ll> b) {
        return (edges[a.first].first - edges[a.first].first/2)*a.second/edges[a.first].second < (edges[b.first].first - edges[b.first].first/2)*b.second/edges[b.first].second;
    }
};
priority_queue <pair <ll, ll> , vector < pair <ll, ll> >, cmp> pq;

int dfs(int v) {
    vis[v] = 1;
    int cnt = 0;
    for (auto u: adj[v]) {
        if (!vis[u.first]) {
            int ret = dfs(u.first);
            cnt += ret;
            //cout << edges[u.second].first << ": " << ret << endl;
            tot += 1ll*edges[u.second].first*ret;
            pq.push({u.second, 1ll*ret});
        }
    }

    return max(1, cnt);
}

int main() {
    int t;
    cin >> t;
    while (t--) {
        cin >> n >> s;
        for (int i=0; i<=n; i++) adj[i].clear();
        edges.clear();
        tot = 0;
        memset(vis, 0, sizeof(vis));
        while (!pq.empty()) pq.pop();
        for (int i=0; i<n-1; i++) {
            int u, v, w, c;
            cin >> u >> v >> w >> c;
            edges.push_back({w, c});
            adj[u].push_back({v, edges.size()-1});
            adj[v].push_back({u, edges.size()-1});
        }
        dfs(1);
        ll res = 0;
        while (tot > s && !pq.empty()) {
            pair <ll, ll> val = pq.top();
            pq.pop();
            tot = tot - edges[val.first].first*val.second + (edges[val.first].first/2)*val.second;
            edges[val.first].first /= 2;
            if (edges[val.first].first) pq.push({val.first, val.second});
            res += edges[val.first].second;
        }
        cout << res << endl;
    }

    return 0;
}


#include <bits/stdc++.h>

#define ll long long int

using namespace std;

const int N = 1e5 + 7;
int n, vis[N];
vector < pair <int, int> > adj[N], edges;
ll s, tot;
struct cmp {
    bool operator()(pair <ll, ll> a, pair <ll, ll> b) {
        double a_diff = double(edges[a.first].first - edges[a.first].first/2)*a.second/double(edges[a.first].second);
        double b_diff = double(edges[b.first].first - edges[b.first].first/2)*b.second/double(edges[b.first].second);
        return (a_diff == b_diff ? edges[a.first].second > edges[b.first].second : a_diff < b_diff);
    }
};
priority_queue <pair <ll, ll> , vector < pair <ll, ll> >, cmp> pq;

int dfs(int v) {
    vis[v] = 1;
    int cnt = 0;
    for (auto u: adj[v]) {
        if (!vis[u.first]) {
            int ret = dfs(u.first);
            cnt += ret;
            //cout << edges[u.second].first << ": " << ret << endl;
            tot += 1ll*edges[u.second].first*ret;
            pq.push({u.second, 1ll*ret});
        }
    }

    return max(1, cnt);
}

int main() {
    int t;
    cin >> t;
    while (t--) {
        cin >> n >> s;
        for (int i=0; i<=n; i++) adj[i].clear();
        edges.clear();
        tot = 0;
        memset(vis, 0, sizeof(vis));
        while (!pq.empty()) pq.pop();
        for (int i=0; i<n-1; i++) {
            int u, v, w, c;
            cin >> u >> v >> w >> c;
            edges.push_back({w, c});
            adj[u].push_back({v, edges.size()-1});
            adj[v].push_back({u, edges.size()-1});
        }
        dfs(1);
        ll res = 0;
        while (tot > s && !pq.empty()) {
            pair <ll, ll> val = pq.top();
            pq.pop();
            //cout << val.first << ": " << edges[val.first].first << " " << edges[val.first].second << endl;
            tot = tot - edges[val.first].first*val.second + (edges[val.first].first/2)*val.second;
            edges[val.first].first /= 2;
            if (edges[val.first].first) pq.push({val.first, val.second});
            res += edges[val.first].second;
        }
        cout << res << endl;
    }

    return 0;
}


#include <bits/stdc++.h>

#define ll long long int

using namespace std;

const int N = 1e5 + 7;
int n, vis[N];
vector < pair <int, int> > adj[N], edges;
ll s, tot;
struct cmp {
    bool operator()(pair <ll, ll> a, pair <ll, ll> b) {
        return (edges[a.first].first - edges[a.first].first/2)*a.second/edges[a.first].second < (edges[b.first].first - edges[b.first].first/2)*b.second/edges[b.first].second;
    }
};
priority_queue <pair <ll, ll> , vector < pair <ll, ll> >, cmp> pq;

int dfs(int v) {
    vis[v] = 1;
    int cnt = 0;
    for (auto u: adj[v]) {
        if (!vis[u.first]) {
            int ret = dfs(u.first);
            cnt += ret;
            //cout << edges[u.second].first << ": " << ret << endl;
            tot += 1ll*edges[u.second].first*ret;
            pq.push({u.second, 1ll*ret});
        }
    }

    return max(1, cnt);
}

int main() {
    int t;
    cin >> t;
    while (t--) {
        cin >> n >> s;
        for (int i=0; i<=n; i++) adj[i].clear();
        edges.clear();
        tot = 0;
        memset(vis, 0, sizeof(vis));
        while (!pq.empty()) pq.pop();
        for (int i=0; i<n-1; i++) {
            int u, v, w, c;
            cin >> u >> v >> w >> c;
            edges.push_back({w, c});
            adj[u].push_back({v, edges.size()-1});
            adj[v].push_back({u, edges.size()-1});
        }
        dfs(1);
        ll res = 0;
        while (tot > s) {
            pair <ll, ll> val = pq.top();
            pq.pop();
            tot = tot - edges[val.first].first*val.second + (edges[val.first].first/2)*val.second;
            edges[val.first].first /= 2;
            pq.push({val.first, val.second});
            res += edges[val.first].second;
        }
        cout << res << endl;
    }

    return 0;
}