#include <iostream>
#include <cstring>
#include <map>
#include <vector>
#include <queue>
#include <algorithm>

#define fi first
#define se second

using namespace std ;

const int N = 1e5+10 , M = 2*N;

typedef long long LL ;
typedef pair<int,int> PII ;

int n ;
LL m ;

int h[N] , e[M] , w[M] , cost[M] , ne[M] , idx ;
void add(int a , int b , int c , int d)
{
    e[idx] = b , w[idx] = c , cost[idx] = d , ne[idx] = h[a] , h[a] = idx++ ;
}

int fa[N] , son[N] ;    //fa[1] = 0
vector<int> leaf ;   //标记叶子节点

int dfs(int u , int pa)
{
    son[u] = 0 ;
    for(int i = h[u] ; ~i ; i = ne[i] )
    {
        int j = e[i] ;
        if(j != pa)
        {
            fa[j] = u ;
            son[u] += dfs(j , u) ;
        }
    }

    if(son[u] == 0)
    {
        leaf.push_back(u) ;
        son[u] = 1;
    }

    return son[u];
}

struct cmp{ //大根堆
    bool operator()(PII &a , PII &b)    //每次挑选变化量最大
    {
        return (LL)(a.fi-a.fi/2)*a.se < (LL)(b.fi-b.fi/2)*b.se ;
    }
};

void dfs2(int u , int fa , priority_queue<PII , vector<PII> , cmp> &heap1 ,
                           priority_queue<PII , vector<PII> , cmp> &heap2 ,LL &sum1 , LL &sum2)
{
    for(int i = h[u] ; ~i ; i = ne[i])
    {
        int j = e[i] ;
        if(j != fa)
        {
            if(cost[i] == 1){
                heap1.push({w[i] , son[j]}) ;
                sum1 += (LL)w[i] * son[j] ;
            }else{
                heap2.push({w[i] , son[j]}) ;
                sum2 += (LL)w[i] * son[j] ;
            }
            dfs2(j , u , heap1 , heap2 , sum1 , sum2) ;
        }
    }
}

int main()
{
    int T ;
    scanf("%d" , &T) ;
    while( T -- )
    {
        cin >> n >> m ;

        memset(h , -1 , sizeof h) ;
        memset(fa , 0 , sizeof fa) ;
        memset(son , 0 , sizeof son) ;

        idx = 0 ;
        leaf.clear() ;

        for(int i = 0 ; i < n-1 ; ++i)
        {
            int a , b , c , d;
            scanf("%d%d%d%d" , &a , &b , &c , &d) ;
            add(a , b , c , d ) ;
            add(b , a , c , d ) ;

        }

        dfs(1 , 0) ; //找到所有叶子节点
        //lalalalala
        priority_queue<PII , vector<PII> , cmp>   heap1 , heap2 ;
        LL sum1 = 0 , sum2 = 0 ;    //总权重

        dfs2(1 , 0 , heap1 , heap2 ,  sum1 , sum2) ;

        vector<int> v1 , v2 ;

        v1.push_back(sum1) ;
        v2.push_back(sum2) ;

        while(heap1.size()){
            auto t = heap1.top() ;
            heap1.pop() ;
            sum1 -= (t.fi - t.fi/2) * t.se;
            if(t.fi/2)
                heap1.push({t.fi/2 , t.se}) ;
            v1.push_back(sum1) ;
        }

        while(heap2.size()){
            auto t = heap2.top() ;
            heap2.pop() ;
            sum2 -= (t.fi - t.fi/2) * t.se;
            if(t.fi/2)
                heap2.push({t.fi/2 , t.se}) ;
            v2.push_back(sum2) ;
        }

        int cnt = 0x3f3f3f3f ;
        int a = v1.size() , b = v2.size() ;

        //for(int i = 0 ; i < a ; ++i)    cout << v1[i] << ' ' ; cout << endl;
        //for(int i = 0 ; i < b ; ++i)    cout << v2[i] << ' ' ; cout << endl;
        for(int i = 0 ; i < a ; ++i)
        {
            //找到小于等于s-v1[i]的最大值所在的下标
            int l = 0 , r = b-1 ;
            int k = m - v1[i] ;
            while(l < r){
                int mid = l+r >> 1 ;
                if(v2[mid] <= k) r = mid ;
                else    l = mid+1 ;
            }

            if(v1[i] + v2[l] <= m)
                cnt = min(cnt , i + l * 2) ;
        }

        cout << cnt << endl;

    }

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int INF = 1e9;

int n;
vector<int> w, c, cnt;
vector<vector<pair<int, int>>> g;

long long getdiff(int i) {
	return w[i] * 1ll * cnt[i] - (w[i] / 2) * 1ll * cnt[i];
}

void dfs(int v, int p = -1) {
	if (g[v].size() == 1) cnt[p] = 1;
	for (auto [to, id] : g[v]) {
		if (id == p) continue;
		dfs(to, id);
		if (p != -1) cnt[p] += cnt[id];
	}
}

vector<long long> get(int clr) {
	set<pair<long long, int>> st;
	long long cur = 0;
	for (int i = 0; i < n - 1; ++i) {
		if (c[i] == clr) {
			st.insert({getdiff(i), i});
			cur += w[i] * 1ll * cnt[i];
		}
	}
	vector<long long> res;
	res.push_back(cur);
	while (cur > 0 && !st.empty()) {
		int id = st.rbegin()->second;
		st.erase(prev(st.end()));
		cur -= getdiff(id);
		res.push_back(cur);
		w[id] /= 2;
		st.insert({getdiff(id), id});
	}
	return res;
}

int main() {
#ifdef _DEBUG
	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
#endif

	int t;
	cin >> t;
	while (t--) {
		long long s;
		cin >> n >> s;
		w = c = cnt = vector<int>(n - 1);
		g = vector<vector<pair<int, int>>>(n);
		for (int i = 0; i < n - 1; ++i) {
			int x, y;
			cin >> x >> y >> w[i] >> c[i];
			--x, --y;
			g[x].push_back({y, i});
			g[y].push_back({x, i});
		}
		dfs(0);
		vector<long long> v1 = get(1), v2 = get(2);
		int pos = int(v2.size()) - 1;
		int ans = INF;
		for (int i = 0; i < int(v1.size()); ++i) {
			while (pos > 0 && v1[i] + v2[pos - 1] <= s) --pos;
			if (v1[i] + v2[pos] <= s) {
				ans = min(ans, i + pos * 2);
			}
		}
		cout << ans << endl;
	}

	return 0;
}


#include <iostream>
#include <cstring>
#include <map>
#include <vector>
#include <queue>
#include <algorithm>

#define fi first
#define se second

using namespace std ;

const int N = 1e5+10 , M = 2*N;

typedef long long LL ;
typedef pair<int,int> PII ;

int n ;
LL m ;

int h[N] , e[M] , w[M] , cost[M] , ne[M] , idx ;
void add(int a , int b , int c , int d)
{
    e[idx] = b , w[idx] = c , cost[idx] = d , ne[idx] = h[a] , h[a] = idx++ ;
}

int fa[N] , son[N] ;    //fa[1] = 0
vector<int> leaf ;   //标记叶子节点

int dfs(int u , int pa)
{
    son[u] = 0 ;
    for(int i = h[u] ; ~i ; i = ne[i] )
    {
        int j = e[i] ;
        if(j != pa)
        {
            fa[j] = u ;
            son[u] += dfs(j , u) ;
        }
    }

    if(son[u] == 0)
    {
        leaf.push_back(u) ;
        son[u] = 1;
    }

    return son[u];
}

struct cmp{ //大根堆
    bool operator()(PII &a , PII &b)    //每次挑选变化量最大
    {
        return (LL)(a.fi-a.fi/2)*a.se < (LL)(b.fi-b.fi/2)*b.se ;
    }
};

void dfs2(int u , int fa , priority_queue<PII , vector<PII> , cmp> &heap1 ,
                           priority_queue<PII , vector<PII> , cmp> &heap2 ,LL &sum1 , LL &sum2)
{
    for(int i = h[u] ; ~i ; i = ne[i])
    {
        int j = e[i] ;
        if(j != fa)
        {
            if(cost[i] == 1){
                heap1.push({w[i] , son[j]}) ;
                sum1 += (LL)w[i] * son[j] ;
            }else{
                heap2.push({w[i] , son[j]}) ;
                sum2 += (LL)w[i] * son[j] ;
            }
            dfs2(j , u , heap1 , heap2 , sum1 , sum2) ;
        }
    }
}

int main()
{
    int T ;
    scanf("%d" , &T) ;
    while( T -- )
    {
        cin >> n >> m ;

        memset(h , -1 , sizeof h) ;
        memset(fa , 0 , sizeof fa) ;
        memset(son , 0 , sizeof son) ;

        idx = 0 ;
        leaf.clear() ;

        for(int i = 0 ; i < n-1 ; ++i)
        {
            int a , b , c , d;
            scanf("%d%d%d%d" , &a , &b , &c , &d) ;
            add(a , b , c , d ) ;
            add(b , a , c , d ) ;

        }

        dfs(1 , 0) ; //找到所有叶子节点

        priority_queue<PII , vector<PII> , cmp>   heap1 , heap2 ;
        LL sum1 = 0 , sum2 = 0 ;    //总权重

        dfs2(1 , 0 , heap1 , heap2 ,  sum1 , sum2) ;

        vector<int> v1 , v2 ;

        v1.push_back(sum1) ;
        v2.push_back(sum2) ;

        while(heap1.size()){
            auto t = heap1.top() ;
            heap1.pop() ;
            sum1 -= (LL)(t.fi - t.fi/2) * t.se;
            if(t.fi/2)
                heap1.push({t.fi/2 , t.se}) ;
            v1.push_back(sum1) ;
        }

        while(heap2.size()){
            auto t = heap2.top() ;
            heap2.pop() ;
            sum2 -= (LL)(t.fi - t.fi/2) * t.se;
            if(t.fi/2)
                heap2.push({t.fi/2 , t.se}) ;
            v2.push_back(sum2) ;
        }

        int cnt = 0x3f3f3f3f ;
        int a = v1.size() , b = v2.size() ;

        //for(int i = 0 ; i < a ; ++i)    cout << v1[i] << ' ' ; cout << endl;
        //for(int i = 0 ; i < b ; ++i)    cout << v2[i] << ' ' ; cout << endl;
        for(int i = 0 ; i < a ; ++i)
        {
            //找到小于等于s-v1[i]的最大值所在的下标
            int l = 0 , r = b-1 ;
            int k = m - v1[i] ;
            while(l < r){
                int mid = l+r >> 1 ;
                if(v2[mid] <= k) r = mid ;
                else    l = mid+1 ;
            }

            if(v1[i] + v2[l] <= m)
                cnt = min(cnt , i + l * 2) ;
        }

        cout << cnt << endl;

    }

    return 0;
}


#include <iostream>
#include <cstring>
#include <map>
#include <vector>
#include <queue>
#include <algorithm>

#define fi first
#define se second

using namespace std ;

const int N = 1e5+10 , M = 2*N;

typedef long long LL ;
typedef pair<int,int> PII ;

int n ;
LL m ;

int h[N] , e[M] , w[M] , cost[M] , ne[M] , idx ;
void add(int a , int b , int c , int d)
{
    e[idx] = b , w[idx] = c , cost[idx] = d , ne[idx] = h[a] , h[a] = idx++ ;
}

int fa[N] , son[N] ;    //fa[1] = 0
vector<int> leaf ;   //标记叶子节点

int dfs(int u , int pa)
{
    son[u] = 0 ;
    for(int i = h[u] ; ~i ; i = ne[i] )
    {
        int j = e[i] ;
        if(j != pa)
        {
            fa[j] = u ;
            son[u] += dfs(j , u) ;
        }
    }

    if(son[u] == 0)
    {
        leaf.push_back(u) ;
        son[u] = 1;
    }

    return son[u];
}

struct cmp{ //大根堆
    bool operator()(PII &a , PII &b)    //每次挑选变化量最大
    {
        return (LL)(a.fi-a.fi/2)*a.se < (LL)(b.fi-b.fi/2)*b.se ;
    }
};

void dfs2(int u , int fa , priority_queue<PII , vector<PII> , cmp> &heap1 ,
                           priority_queue<PII , vector<PII> , cmp> &heap2 ,LL &sum1 , LL &sum2)
{
    for(int i = h[u] ; ~i ; i = ne[i])
    {
        int j = e[i] ;
        if(j != fa)
        {
            if(cost[i] == 1){
                heap1.push({w[i] , son[j]}) ;
                sum1 += (LL)w[i] * son[j] ;
            }else{
                heap2.push({w[i] , son[j]}) ;
                sum2 += (LL)w[i] * son[j] ;
            }
            dfs2(j , u , heap1 , heap2 , sum1 , sum2) ;
        }
    }
}

int main()
{
    int T ;
    scanf("%d" , &T) ;
    while( T -- )
    {
        cin >> n >> m ;

        memset(h , -1 , sizeof h) ;
        memset(fa , 0 , sizeof fa) ;
        memset(son , 0 , sizeof son) ;

        idx = 0 ;
        leaf.clear() ;

        for(int i = 0 ; i < n-1 ; ++i)
        {
            int a , b , c , d;
            scanf("%d%d%d%d" , &a , &b , &c , &d) ;
            add(a , b , c , d ) ;
            add(b , a , c , d ) ;

        }

        dfs(1 , 0) ; //找到所有叶子节点

        priority_queue<PII , vector<PII> , cmp>   heap1 , heap2 ;
        LL sum1 = 0 , sum2 = 0 ;    //总权重

        dfs2(1 , 0 , heap1 , heap2 ,  sum1 , sum2) ;

        vector<int> v1 , v2 ;

        v1.push_back(sum1) ;
        v2.push_back(sum2) ;

        while(sum1){
            auto t = heap1.top() ;
            heap1.pop() ;
            sum1 -= (t.fi - t.fi/2) * t.se;
            heap1.push({t.fi/2 , t.se}) ;
            v1.push_back(sum1) ;
        }

        while(sum2){
            auto t = heap2.top() ;
            heap2.pop() ;
            sum2 -= (t.fi - t.fi/2) * t.se;
            heap2.push({t.fi/2 , t.se}) ;
            v2.push_back(sum2) ;
        }

        int cnt = 0x3f3f3f3f ;
        int a = v1.size() , b = v2.size() ;

        //for(int i = 0 ; i < a ; ++i)    cout << v1[i] << ' ' ; cout << endl;
        //for(int i = 0 ; i < b ; ++i)    cout << v2[i] << ' ' ; cout << endl;
        for(int i = 0 ; i < a ; ++i)
        {
            //找到小于等于s-v1[i]的最大值所在的下标
            int l = 0 , r = b-1 ;
            int k = m - v1[i] ;
            while(l < r){
                int mid = l+r >> 1 ;
                if(v2[mid] <= k) r = mid ;
                else    l = mid+1 ;
            }

            if(v1[i] + v2[l] <= m)
                cnt = min(cnt , i + l * 2) ;
        }

        cout << cnt << endl;

    }

    return 0;
}


#include<bits/stdc++.h>

using namespace std;

#define PB push_back
#define MT make_tuple

using namespace std;

typedef long long LL;

typedef tuple<int, int, int> TI;

const int N = 100005;
const int INF = 0x3f3f3f3f;

vector<TI> G[N];

int deg[N], val[N], cst[N];

LL v1[N*20], v2[N*20], tp1, tp2;

int n;

LL S;

int dfs(int u, int f){
    int isLeef=1;
    for(int i=0;i<G[u].size();++i){
        int x,y,z;
        tie(x,y,z)=G[u][i];
        if(x==f)continue;
        else{
            isLeef=0;
            val[x]=y;
            cst[x]=z;
            deg[u]+=dfs(x,u);
        }
    }
    if(isLeef)return deg[u]=1;
    else return deg[u];
}

int main(){
    int T;scanf("%d",&T);
    while(T--){
        scanf("%d%lld", &n, &S);
        int x, y, z, c;
        for(int i=1;i<=n;++i){
            G[i].clear();
            deg[i]=val[i]=0;
        }
        for(int i=1;i<n;++i){
            scanf("%d%d%d%d", &x, &y, &z, &c);
            G[x].PB(MT(y,z,c));
            G[y].PB(MT(x,z,c));
        }

        dfs(1,0);

        LL s=0;
        for(int i=1;i<=n;++i){
            s+=1ll*val[i]*deg[i];
        }

        tp1=tp2=0;
        for(int i=1;i<=n;++i){
            if(cst[i]==1){
                for(int t=val[i];t>0;t>>=1){
                    v1[++tp1]=1ll*(t-t/2)*deg[i];
                }
            }else{
                for(int t=val[i];t>0;t>>=1){
                    v2[++tp2]=1ll*(t-t/2)*deg[i];
                }
            }
        }

        sort(v1+1,v1+tp1+1,greater<LL>());
        sort(v2+1,v2+tp2+1,greater<LL>());

        int res=INF;
        if(s<=S){
            printf("0\n");
            continue;
        }

        int j=1;
        for(;j<=tp2;++j){
            s-=v2[j];
            if(s<=S)break;
        }
        if(j>tp2)--j;
        if(s<=S)res=min(res,2*j);

        for(int i=1;i<=tp1;++i){
            s-=v1[i];
            while(j&&s+v2[j]<=S){
                s+=v2[j];
                --j;
            }
            if(s<=S){
                res=min(res,i+2*j);
            }
        }

        printf("%d\n",res);
    }

    return 0;
}


#include<bits/stdc++.h>

using namespace std;

#define PB push_back
#define MT make_tuple

using namespace std;

typedef long long LL;

typedef tuple<int, int, int> TI;

const int N = 100005;
const int INF = 0x3f3f3f3f;

vector<TI> G[N];

int deg[N], val[N], cst[N];

LL v1[N*20], v2[N*20], tp1, tp2;

int n;

LL S;

int dfs(int u, int f){
    int isLeef=1;
    for(int i=0;i<G[u].size();++i){
        int x,y,z;
        tie(x,y,z)=G[u][i];
        if(x==f)continue;
        else{
            isLeef=0;
            val[x]=y;
            cst[x]=z;
            deg[u]+=dfs(x,u);
        }
    }
    if(isLeef)return deg[u]=1;
    else return deg[u];
}

int main(){
    int T;scanf("%d",&T);
    while(T--){
        scanf("%d%lld", &n, &S);
        int x, y, z, c;
        for(int i=1;i<=n;++i){
            G[i].clear();
            deg[i]=val[i]=0;
        }
        for(int i=1;i<n;++i){
            scanf("%d%d%d%d", &x, &y, &z, &c);
            G[x].PB(MT(y,z,c));
            G[y].PB(MT(x,z,c));
        }

        dfs(1,0);

        LL s=0;
        for(int i=1;i<=n;++i){
            s+=1ll*val[i]*deg[i];
        }

        tp1=tp2=0;
        for(int i=1;i<=n;++i){
            if(cst[i]==1){
                for(int t=val[i];t>0;t>>=1){
                    v1[++tp1]=1ll*(t-t/2)*deg[i];
                }
            }else{
                for(int t=val[i];t>0;t>>=1){
                    v2[++tp2]=1ll*(t-t/2)*deg[i];
                }
            }
        }

        sort(v1+1,v1+tp1+1,greater<LL>());
        sort(v2+1,v2+tp2+1,greater<LL>());

        int res=INF;
        if(s<=S){
            printf("0\n");
            continue;
        }

        int j=1;
        for(;j<=tp2;++j){
            s-=v2[j];
            if(s<=S)break;
        }
        if(s<=S)res=min(res,2*j);

        for(int i=1;i<=tp1;++i){
            s-=v1[i];
            while(j&&s+v2[j]<=S){
                s+=v2[j];
                --j;
            }
            if(s<=S){
                res=min(res,i+2*j);
            }
        }

        printf("%d\n",res);
    }

    return 0;
}


#include<bits/stdc++.h>

using namespace std;

#define PB push_back
#define MT make_tuple

using namespace std;

typedef long long LL;

typedef tuple<int, int, int> TI;

const int N = 100005;
const int INF = 0x3f3f3f3f;

vector<TI> G[N];

int deg[N], val[N], cst[N];

LL v1[N*20], v2[N*20], tp1, tp2;

int n;

LL S;

int dfs(int u, int f){
    int isLeef=1;
    for(int i=0;i<G[u].size();++i){
        int x,y,z;
        tie(x,y,z)=G[u][i];
        if(x==f)continue;
        else{
            isLeef=0;
            val[x]=y;
            cst[x]=z;
            deg[u]+=dfs(x,u);
        }
    }
    if(isLeef)return deg[u]=1;
    else return deg[u];
}

int main(){
    int T;scanf("%d",&T);
    while(T--){
        scanf("%d%lld", &n, &S);
        int x, y, z, c;
        for(int i=1;i<=n;++i){
            G[i].clear();
            deg[i]=val[i]=0;
        }
        for(int i=1;i<n;++i){
            scanf("%d%d%d%d", &x, &y, &z, &c);
            G[x].PB(MT(y,z,c));
            G[y].PB(MT(x,z,c));
        }

        dfs(1,0);

        LL s=0;
        for(int i=1;i<=n;++i){
            s+=1ll*val[i]*deg[i];
        }

        tp1=tp2=0;
        for(int i=1;i<=n;++i){
            if(cst[i]==1){
                for(int t=val[i];t>0;t>>=1){
                    v1[++tp1]=1ll*(t-t/2)*deg[i];
                }
            }else{
                for(int t=val[i];t>0;t>>=1){
                    v2[++tp2]=1ll*(t-t/2)*deg[i];
                }
            }
        }

        sort(v1+1,v1+tp1+1,greater<LL>());
        sort(v2+1,v2+tp2+1,greater<LL>());

        int res=INF;
        if(s<=S){
            printf("0\n");
            continue;
        }

        int j=1;
        for(;j<=tp2;++j){
            s-=v2[j];
            if(s<=S)break;
        }
        if(j>tp1)--j;
        if(s<=S)res=min(res,2*j);

        for(int i=1;i<=tp1;++i){
            s-=v1[i];
            while(j&&s+v2[j]<=S){
                s+=v2[j];
                --j;
            }
            if(s<=S){
                res=min(res,i+2*j);
            }
        }

        printf("%d\n",res);
    }

    return 0;
}


#include<bits/stdc++.h>

using namespace std;

#define PB push_back
#define MT make_tuple

using namespace std;

typedef long long LL;

typedef tuple<int, int, int> TI;

const int N = 100005;
const int INF = 0x3f3f3f3f;

vector<TI> G[N];

int deg[N], val[N], cst[N];

LL v1[N*20], v2[N*20], tp1, tp2;

int n;

LL S;

int dfs(int u, int f){
    int isLeef=1;
    for(int i=0;i<G[u].size();++i){
        int x,y,z;
        tie(x,y,z)=G[u][i];
        if(x==f)continue;
        else{
            isLeef=0;
            val[x]=y;
            cst[x]=z;
            deg[u]+=dfs(x,u);
        }
    }
    if(isLeef)return deg[u]=1;
    else return deg[u];
}

int main(){
    int T;scanf("%d",&T);
    while(T--){
        scanf("%d%lld", &n, &S);
        int x, y, z, c;
        for(int i=1;i<=n;++i){
            G[i].clear();
            deg[i]=val[i]=0;
        }
        for(int i=1;i<n;++i){
            scanf("%d%d%d%d", &x, &y, &z, &c);
            G[x].PB(MT(y,z,c));
            G[y].PB(MT(x,z,c));
        }

        dfs(1,0);

        LL s=0;
        for(int i=1;i<=n;++i){
            s+=1ll*val[i]*deg[i];
        }

        tp1=tp2=0;
        for(int i=1;i<=n;++i){
            if(cst[i]==1){
                for(int t=val[i];t>0;t>>=1){
                    v1[++tp1]=1ll*(t-t/2)*deg[i];
                }
            }else{
                for(int t=val[i];t>0;t>>=1){
                    v2[++tp2]=1ll*(t-t/2)*deg[i];
                }
            }
        }

        sort(v1+1,v1+tp1+1,greater<LL>());
        sort(v2+1,v2+tp2+1,greater<LL>());

        int res=INF;
        if(s<=S){
            printf("0\n");
            continue;
        }

        for(int i=1;i<=tp1;++i)printf("%lld ",v1[i]);
        printf("\n");
        for(int i=1;i<=tp2;++i)printf("%lld ",v2[i]);
        printf("\n");

        int j=1;
        for(;j<=tp2;++j){
            s-=v2[j];
            if(s<=S)break;
        }
        if(s<=S)res=min(res,2*j);
        printf("%lld %d\n",s,j);

        for(int i=1;i<=tp1;++i){
            s-=v1[i];
            while(j&&s+v2[j]<=S){
                s+=v2[j];
                --j;
            }
            if(s<=S){
                res=min(res,i+2*j);
            }
        }

        printf("%d\n",res);
    }

    return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <stack>
#include <string>
#include <cstring>
#include <queue>
#include <map>
#include <set>
#include <cmath>
#include <climits>

using namespace std;

const int N = 3e5 + 5000;
int n, m, T, w[N], c[N], cnt[N], flag[N];
vector<pair<int, pair<int, int>>> v[N];
vector<int> nxt[N];
long long s;
vector<long long> a, b;

struct cmp {
    bool operator () (int a, int b) {
        return 1ll * cnt[a] * (w[a] - w[a] / 2) < 1ll * cnt[b] * (w[b] - w[b] / 2);
    }
};
priority_queue<int, vector<int>, cmp> q1, q2;

void dfs(int x, int fa) {
    flag[x] = 1;

    for (auto &y : v[x]) {
        if (y.first == fa) {
            continue;
        }

        flag[x] = 0;
        dfs(y.first, x);

        cnt[x] += cnt[y.first];

        nxt[x].push_back(y.first);
        w[y.first] = y.second.first;
        c[y.first] = y.second.second;
    }

    if (flag[x]) {
        cnt[x] = 1;
    }
}

int main()
{
#ifdef ONLINE_JUDGE
#else
    freopen("in1.txt", "r", stdin);
    // freopen("w.txt", "w", stdout);
#endif
    ios::sync_with_stdio(false);

    for (cin >> T; T--;) {
        cin >> n >> s;
        for (int i = 1; i <= n; i++) {
            v[i].clear();
            cnt[i] = 0;
        }

        for (int a, b, w, c, i = 1; i < n; i++) {
            cin >> a >> b >> w >> c;

            v[a].push_back(make_pair(b, make_pair(w, c)));
            v[b].push_back(make_pair(a, make_pair(w, c)));
        }

        dfs(1, 0);
        a.clear();
        b.clear();
        while (!q1.empty()) {
            q1.pop();
        }
        while (!q2.empty()) {
            q2.pop();
        }

        long long sum = 0;
        for (int i = 2; i <= n; i++) {
            if (c[i] == 1) {
                q1.push(i);
            } else {
                q2.push(i);
            }
            sum += 1ll * cnt[i] * w[i];
        }

        long long delt = sum - s;
        // cout << s << " " << sum << " " << delt << endl;
        if (delt <= 0) {
            cout << 0 << endl;
            continue;
        }

        a.push_back(0);
        long long sum1 = 0;
        while (sum1 < delt and !q1.empty()) {
            int x = q1.top();
            q1.pop();

            sum1 += 1ll * cnt[x] * (w[x] - w[x] / 2);
            a.push_back(sum1);
            // cout << sum1 << endl;
            w[x] /= 2;
            if (w[x] > 0) {
                q1.push(x);
            }
        }

        b.push_back(0);
        long long sum2 = 0;
        while (sum2 < delt and !q2.empty()) {
            int x = q2.top();
            q2.pop();

            sum2 += 1ll * cnt[x] * (w[x] - w[x] / 2);
            b.push_back(sum2);
            w[x] /= 2;
            if (w[x] > 0) {
                q2.push(x);
            }
        }

        long long ans = LLONG_MAX;

        for (int i = 0; i < a.size(); i++) {
            int p = lower_bound(b.begin(), b.end(), delt - a[i]) - b.begin();

            if (p != b.size()) {
                ans = min(ans, i + p * 2ll);
            }
        }

        cout << ans << endl;
    }
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <stack>
#include <string>
#include <cstring>
#include <queue>
#include <map>
#include <set>
#include <cmath>
#include <climits>

using namespace std;

const int N = 3e5 + 5000;
int n, m, T, w[N], c[N], cnt[N], flag[N];
vector<pair<int, pair<int, int>>> v[N];
vector<int> nxt[N];
long long s;
vector<long long> a, b;

struct cmp {
    bool operator () (int a, int b) {
        return 1ll * cnt[a] * (w[a] - w[a] / 2) < 1ll * cnt[b] * (w[b] - w[b] / 2);
    }
};
priority_queue<int, vector<int>, cmp> q1, q2;

void dfs(int x, int fa) {
    flag[x] = 1;

    for (auto &y : v[x]) {
        if (y.first == fa) {
            continue;
        }

        flag[x] = 0;
        dfs(y.first, x);

        cnt[x] += cnt[y.first];

        nxt[x].push_back(y.first);
        w[y.first] = y.second.first;
        c[y.first] = y.second.second;
    }

    if (flag[x]) {
        cnt[x] = 1;
    }
}

int main()
{
#ifdef ONLINE_JUDGE
#else
    freopen("in1.txt", "r", stdin);
    // freopen("w.txt", "w", stdout);
#endif
    ios::sync_with_stdio(false);

    for (cin >> T; T--;) {
        cin >> n >> s;
        for (int i = 1; i <= n; i++) {
            v[i].clear();
            cnt[i] = 0;
        }

        for (int a, b, w, c, i = 1; i < n; i++) {
            cin >> a >> b >> w >> c;

            v[a].push_back(make_pair(b, make_pair(w, c)));
            v[b].push_back(make_pair(a, make_pair(w, c)));
        }

        dfs(1, 0);
        a.clear();
        b.clear();
        while (!q1.empty()) {
            q1.pop();
        }
        while (!q2.empty()) {
            q2.pop();
        }

        long long sum = 0;
        for (int i = 2; i <= n; i++) {
            if (c[i] == 1) {
                q1.push(i);
            } else {
                q2.push(i);
            }
            sum += 1ll * cnt[i] * w[i];
        }

        long long delt = sum - s;
        // cout << s << " " << sum << endl;
        if (delt <= 0) {
            cout << 0 << endl;
            continue;
        }

        long long sum1 = 0;
        while (sum1 < delt and !q1.empty()) {
            int x = q1.top();
            q1.pop();

            sum1 += 1ll * cnt[x] * (w[x] - w[x] / 2);
            a.push_back(sum1);
            w[x] /= 2;
            if (w[x] > 0) {
                q1.push(x);
            }
        }

        long long sum2 = 0;
        while (sum2 < delt and !q2.empty()) {
            int x = q2.top();
            q2.pop();

            sum2 += 1ll * cnt[x] * (w[x] - w[x] / 2);
            b.push_back(sum2);
            w[x] /= 2;
            if (w[x] > 0) {
                q2.push(x);
            }
        }

        long long ans = LLONG_MAX;
        int p = lower_bound(b.begin(), b.end(), delt) - b.begin();
        if (p != b.size()) {
            ans = min(ans, (p + 1) * 2ll);
        }

        for (int i = 0; i < a.size(); i++) {
            int p = lower_bound(b.begin(), b.end(), delt - a[i]) - b.begin();

            if (p == b.size())
                continue;
            ans = min(ans, 1ll + i + (p + 1) * 2);
        }

        cout << ans << endl;
    }
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <stack>
#include <string>
#include <cstring>
#include <queue>
#include <map>
#include <set>
#include <cmath>
#include <climits>

using namespace std;

const int N = 3e5 + 5000;
int n, m, T, w[N], c[N], cnt[N], flag[N];
vector<pair<int, pair<int, int>>> v[N];
vector<int> nxt[N];
long long s;
vector<long long> a, b;

struct cmp {
    bool operator () (int a, int b) {
        return 1ll * cnt[a] * (w[a] - w[a] / 2) < 1ll * cnt[b] * (w[b] - w[b] / 2);
    }
};
priority_queue<int, vector<int>, cmp> q1, q2;

void dfs(int x, int fa) {
    flag[x] = 1;

    for (auto &y : v[x]) {
        if (y.first == fa) {
            continue;
        }

        flag[x] = 0;
        dfs(y.first, x);

        cnt[x] += cnt[y.first];

        nxt[x].push_back(y.first);
        w[y.first] = y.second.first;
        c[y.first] = y.second.second;
    }

    if (flag[x]) {
        cnt[x] = 1;
    }
}

int main()
{
#ifdef ONLINE_JUDGE
#else
    freopen("in1.txt", "r", stdin);
    // freopen("w.txt", "w", stdout);
#endif
    ios::sync_with_stdio(false);

    for (cin >> T; T--;) {
        cin >> n >> s;
        for (int i = 1; i <= n; i++) {
            v[i].clear();
            cnt[i] = 0;
        }

        for (int a, b, w, c, i = 1; i < n; i++) {
            cin >> a >> b >> w >> c;

            v[a].push_back(make_pair(b, make_pair(w, c)));
            v[b].push_back(make_pair(a, make_pair(w, c)));
        }

        dfs(1, 0);
        a.clear();
        b.clear();
        while (!q1.empty()) {
            q1.pop();
        }
        while (!q2.empty()) {
            q2.pop();
        }

        long long sum = 0;
        for (int i = 2; i <= n; i++) {
            if (c[i] == 1) {
                q1.push(i);
            } else {
                q2.push(i);
            }
            sum += 1ll * cnt[i] * w[i];
        }

        long long delt = sum - s;
        // cout << s << " " << sum << " " << delt << endl;
        if (delt <= 0) {
            cout << 0 << endl;
            continue;
        }

        long long sum1 = 0;
        while (sum1 < delt and !q1.empty()) {
            int x = q1.top();
            q1.pop();

            sum1 += 1ll * cnt[x] * (w[x] - w[x] / 2);
            a.push_back(sum1);
            // cout << sum1 << endl;
            w[x] /= 2;
            if (w[x] > 0) {
                q1.push(x);
            }
        }

        long long sum2 = 0;
        while (sum2 < delt and !q2.empty()) {
            int x = q2.top();
            q2.pop();

            sum2 += 1ll * cnt[x] * (w[x] - w[x] / 2);
            b.push_back(sum2);
            w[x] /= 2;
            if (w[x] > 0) {
                q2.push(x);
            }
        }
        if (b.size() == 0)
            b.push_back(0);
        else
            b.push_back(*b.end());
        long long ans = LLONG_MAX;
        int p = lower_bound(b.begin(), b.end() - 1, delt) - b.begin();
        if (b[p] >= delt) {
            ans = min(ans, (p + 1) * 2ll);
        }
        // cout << ans << endl;
        for (int i = 0; i < a.size(); i++) {
            int p = lower_bound(b.begin(), b.end() - 1, delt - a[i]) - b.begin();

            if (b[p] + a[i] >= delt) {
                // cout << i << " " << a[i] << " " << b[p] << " " << delt << endl;
                if (p == b.size() - 1) {
                    p = -1;
                }
                ans = min(ans, 1ll + i + (p + 1) * 2);
            }
        }

        cout << ans << endl;
    }
}


#include<bits/stdc++.h>
#define N 100009
using namespace std;

inline long long read(){
	long long x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f;
}

struct cow{
	long long v,w,next,op;
}E[N<<2];
long long head[N];

long long tot=0;
void add(long long u,long long v,long long w,long long op){
	E[++tot].v=v;E[tot].w=w;E[tot].op=op;
	E[tot].next=head[u];head[u]=tot;
	E[++tot].v=u;E[tot].w=w;E[tot].op=op;
	E[tot].next=head[v];head[v]=tot;
}

long long num[N],val[N],tag[N];
long long sum;

void dfs(long long u,long long fa,long long dis){
	bool flag=true;
	for(long long i=head[u];i;i=E[i].next){
		long long v=E[i].v;
		if(v==fa)continue;
		flag=false;
		dfs(v,u,dis+E[i].w);
		num[u]+=num[v];
		val[v]=E[i].w;
		tag[v]=E[i].op;
	}
	if(flag){
		sum+=dis;
		num[u]=1;
	}
}

priority_queue<pair<long long,long long> >Q1,Q2;
pair<long long,long long> p;

void Clear(long long n){
	tot=0;sum=0;
	for(long long i=0;i<=n;i++){
		head[i]=val[i]=num[i]=tag[i]=0;
	}
	while(!Q1.empty())Q1.pop();
	while(!Q2.empty())Q2.pop();
}

long long ans1[N],ans2[N];

void France(){
	long long n=read(),S=read(),u,v,w,op;
	Clear(n);
	for(long long i=1;i<n;i++){
		u=read();v=read();w=read();op=read();
		add(u,v,w,op);
	}
	dfs(1,0,0);
	for(long long i=2;i<=n;i++){
		if(tag[i]==1)Q1.push(make_pair(num[i]*(val[i]-val[i]/2),i));
		if(tag[i]==2)Q2.push(make_pair(num[i]*(val[i]-val[i]/2),i));
	}

	long long cnt1=0,cnt2=0,tmp;
	tmp=sum;
	while(tmp>S&&!Q1.empty()){
		p=Q1.top();Q1.pop();
		if(p.first==0)break;
		tmp-=p.first;cnt1++;
		ans1[cnt1]=ans1[cnt1-1]+p.first;
		long long id=p.second;
		val[id]/=2;
		Q1.push(make_pair(num[id]*(val[id]-val[id]/2),id));
	}

	tmp=sum;
	while(tmp>S&&!Q2.empty()){
		p=Q2.top();Q2.pop();
		if(p.first==0)break;
		tmp-=p.first;cnt2++;
		ans2[cnt2]=ans2[cnt2-1]+p.first;
		long long id=p.second;
		val[id]/=2;
		Q2.push(make_pair(num[id]*(val[id]-val[id]/2),id));
	}

	long long ans=LONG_LONG_MAX;
	for(long long i=0;i<=cnt1;i++){
		for(long long j=0;j<=cnt2;j++){
			if(sum-ans1[i]-ans2[j]<=S){
				ans=min(ans,i+j+j);break;
			}
		}
	}

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

	return;
}

int main(){
	long long T=read();
	while(T--)France();
	return 0;
}


#include<bits/stdc++.h>
#define N 100009
using namespace std;

inline long long read(){
	long long x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f;
}

struct cow{
	long long v,w,next,op;
}E[N<<2];
long long head[N];

long long tot=0;
void add(long long u,long long v,long long w,long long op){
	E[++tot].v=v;E[tot].w=w;E[tot].op=op;
	E[tot].next=head[u];head[u]=tot;
	E[++tot].v=u;E[tot].w=w;E[tot].op=op;
	E[tot].next=head[v];head[v]=tot;
}

long long num[N],val[N],tag[N];
long long sum;

void dfs(long long u,long long fa,long long dis){
	bool flag=true;
	for(long long i=head[u];i;i=E[i].next){
		long long v=E[i].v;
		if(v==fa)continue;
		flag=false;
		dfs(v,u,dis+E[i].w);
		num[u]+=num[v];
		val[v]=E[i].w;
		tag[v]=E[i].op;
	}
	if(flag){
		sum+=dis;
		num[u]=1;
	}
}

priority_queue<pair<long long,long long> >Q1,Q2;
pair<long long,long long> p;

void Clear(long long n){
	tot=0;sum=0;
	for(long long i=0;i<=n;i++){
		head[i]=val[i]=num[i]=tag[i]=0;
	}
	while(!Q1.empty())Q1.pop();
	while(!Q2.empty())Q2.pop();
}

long long ans1[N],ans2[N];

void France(){
	long long n=read(),S=read(),u,v,w,op;
	Clear(n);
	for(long long i=1;i<n;i++){
		u=read();v=read();w=read();op=read();
		add(u,v,w,op);
	}
	dfs(1,0,0);
	for(long long i=2;i<=n;i++){
		if(tag[i]==1)Q1.push(make_pair(num[i]*(val[i]-val[i]/2),i));
		if(tag[i]==2)Q2.push(make_pair(num[i]*(val[i]-val[i]/2),i));
	}

	long long cnt1=0,cnt2=0,tmp;
	tmp=sum;
	while(tmp>S&&!Q1.empty()){
		p=Q1.top();Q1.pop();
		if(p.first==0)break;
		tmp-=p.first;cnt1++;
		ans1[cnt1]=ans1[cnt1-1]+p.first;
		long long id=p.second;
		val[id]/=2;
		Q1.push(make_pair(num[id]*(val[id]-val[id]/2),id));
	}

	tmp=sum;
	while(tmp>S&&!Q2.empty()){
		p=Q2.top();Q2.pop();
		if(p.first==0)break;
		tmp-=p.first;cnt2++;
		ans2[cnt2]=ans2[cnt2-1]+p.first;
		long long id=p.second;
		val[id]/=2;
		Q2.push(make_pair(num[id]*(val[id]-val[id]/2),id));
	}

	long long ans=1000000000000000;
	for(long long i=0;i<=cnt1;i++){
		for(long long j=0;j<=cnt2;j++){
			if(sum-ans1[i]-ans2[j]<=S){
				ans=min(ans,i+j+j);break;
			}
		}
	}

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

	return;
}

int main(){
	long long T=read();
	while(T--)France();
	return 0;
}


#include<bits/stdc++.h>
#define N 100009
using namespace std;

inline long long read(){
	long long x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f;
}

struct cow{
	long long v,w,next,op;
}E[N<<2];
long long head[N];

long long tot=0;
void add(long long u,long long v,long long w,long long op){
	E[++tot].v=v;E[tot].w=w;E[tot].op=op;
	E[tot].next=head[u];head[u]=tot;
	E[++tot].v=u;E[tot].w=w;E[tot].op=op;
	E[tot].next=head[v];head[v]=tot;
}

long long num[N],val[N],tag[N];
long long sum;

void dfs(long long u,long long fa,long long dis){
	bool flag=true;
	for(long long i=head[u];i;i=E[i].next){
		long long v=E[i].v;
		if(v==fa)continue;
		flag=false;
		dfs(v,u,dis+E[i].w);
		num[u]+=num[v];
		val[v]=E[i].w;
		tag[v]=E[i].op;
	}
	if(flag){
		sum+=dis;
		num[u]=1;
	}
}

priority_queue<pair<long long,long long> >Q1,Q2;
pair<long long,long long> p;

void Clear(long long n){
	tot=0;sum=0;
	for(long long i=0;i<=n;i++){
		head[i]=val[i]=num[i]=tag[i]=0;
	}
	while(!Q1.empty())Q1.pop();
	while(!Q2.empty())Q2.pop();
}

long long ans1[N],ans2[N];

void France(){
	long long n=read(),S=read(),u,v,w,op;
	Clear(n);
	for(long long i=1;i<n;i++){
		u=read();v=read();w=read();op=read();
		add(u,v,w,op);
	}
	dfs(1,0,0);
	for(long long i=2;i<=n;i++){
		if(tag[i]==1)Q1.push(make_pair(num[i]*(val[i]-val[i]/2),i));
		if(tag[i]==2)Q2.push(make_pair(num[i]*(val[i]-val[i]/2),i));
	}

	long long cnt1=0,cnt2=0,tmp,sum1=0,sum2=0;
	tmp=sum;
	while(tmp>S&&!Q1.empty()){
		p=Q1.top();Q1.pop();
		if(p.first==0)break;
		tmp-=p.first;cnt1++;
		sum1+=p.first;ans1[cnt1]=sum1;
		long long id=p.second;
		val[id]/=2;
		Q1.push(make_pair(num[id]*(val[id]-val[id]/2),id));
	}

	tmp=sum;
	while(tmp>S&&!Q2.empty()){
		p=Q2.top();Q2.pop();
		if(p.first==0)break;
		tmp-=p.first;cnt2++;
		sum2+=p.first;ans2[cnt2]=sum2;
		long long id=p.second;
		val[id]/=2;
		Q2.push(make_pair(num[id]*(val[id]-val[id]/2),id));
	}

	long long ans=1000000000000000;
	for(long long i=0;i<=cnt1;i++){
		for(long long j=0;j<=cnt2;j++){
			if(sum-ans1[i]-ans2[j]<=S){
				ans=min(ans,i+j+j);break;
			}
		}
	}

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

	return;
}

int main(){
	long long T=read();
	while(T--)France();
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
struct cmp
{
    bool operator()(const pair<int,int> &a, const pair<int,int> &b)
    {
        if(1LL*(a.first-(a.first/2))*a.second!=1LL*(b.first-(b.first/2))*b.second)
			return 1LL*(a.first-(a.first/2))*a.second>1LL*(b.first-(b.first/2))*b.second;
		return a.first>b.first;
    }
};
int d[1000010],o[1000010],nxt[1000010],to[1000010],head[1000010],val[1000010],f[1000010],t[1000010],cnt,cnt1,cnt2,n,m,ans;
multiset<pair<int,int>,cmp>s1,s2;
long long ans1[5000003],ans2[5000003];
void dfs(int x,int fa,int from)
{
	if(d[x]==1&&x!=1)
	{
		t[from]=1;
		return;
	}
	for(int i=head[x];i;i=nxt[i])
		if(to[i]!=fa)
		{
			dfs(to[i],x,i);
			t[from]+=t[i];
		}
}
int bs(long long k)
{
	int res=cnt2,l=0,r=cnt2;
	while(l<=r)
	{
		int mid=(l+r)>>1;
		if(ans2[mid]>=k)
		{
			res=mid;
			r=mid-1;
		}
		else
			l=mid+1;
	}
	return res;
}
int main()
{
	int T,i,u,v,w,qwq;
	long long S,tS;
	cin>>T;
	while(T--)
	{
		s1.clear();
		s2.clear();
		cnt=cnt1=cnt2=0;
		cin>>n;
		ans=1000000007;
		m=(n-1)<<1;
		for(i=1;i<=n;i++)
		{
			head[i]=0;
			d[i]=0;
		}
		for(i=1;i<=m;i++)
			t[i]=0;
		cin>>S;
		S=-S;
		for(i=1;i<n;i++)
		{
			cin>>u>>v>>w>>qwq;
			to[++cnt]=v;
			val[cnt]=w;
			f[cnt]=qwq;
			nxt[cnt]=head[u];
			head[u]=cnt;
			to[++cnt]=u;
			val[cnt]=w;
			f[cnt]=qwq;
			nxt[cnt]=head[v];
			head[v]=cnt;
			d[u]++;
			d[v]++;
		}
		dfs(1,1,0);
		for(i=1;i<=m;i++)
			if(t[i])
			{
				S+=1LL*val[i]*t[i];
				if(f[i]==1)
					s1.insert(make_pair(val[i],t[i]));
				else
					s2.insert(make_pair(val[i],t[i]));
			}
		tS=0;
		while(tS<=S)
		{
			if(s1.empty())
				break;
			pair<int,int>tmp=*s1.begin();
			s1.erase(s1.begin());
			tS+=1LL*(tmp.first-(tmp.first/2))*tmp.second;
			tmp.first/=2;
			if(tmp.first)
				s1.insert(tmp);
			ans1[++cnt1]=tS;
		}
		tS=0;
		while(tS<=S)
		{
			if(s2.empty())
				break;
			pair<int,int>tmp=*s2.begin();
			s2.erase(s2.begin());
			tS+=1LL*(tmp.first-(tmp.first/2))*tmp.second;
			tmp.first/=2;
			if(tmp.first)
				s2.insert(tmp);
			ans2[++cnt2]=tS;
		}
		for(i=0;i<=cnt1;i++)
		{
			if(ans1[i]+ans2[cnt2]<S)
				continue;
			if(ans1[i]>=S)
			{
				ans=min(ans,i);
				break;
			}
			ans=min(ans,i+2*bs(S-ans1[i]));
		}
		cout<<ans<<endl;
	}
    return 0;
}


#include<bits/stdc++.h>
#define N 100009
using namespace std;

inline long long read(){
	long long x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f;
}

struct cow{
	long long v,w,next,op;
}E[N<<2];
long long head[N];

long long tot=0;
void add(long long u,long long v,long long w,long long op){
	E[++tot].v=v;E[tot].w=w;E[tot].op=op;
	E[tot].next=head[u];head[u]=tot;
	E[++tot].v=u;E[tot].w=w;E[tot].op=op;
	E[tot].next=head[v];head[v]=tot;
}

long long num[N],val[N],tag[N];
long long sum;

void dfs(long long u,long long fa,long long dis){
	bool flag=true;
	for(long long i=head[u];i;i=E[i].next){
		long long v=E[i].v;
		if(v==fa)continue;
		flag=false;
		dfs(v,u,dis+E[i].w);
		num[u]+=num[v];
		val[v]=E[i].w;
		tag[v]=E[i].op;
	}
	if(flag){
		sum+=dis;
		num[u]=1;
	}
}

priority_queue<pair<long long,long long> >Q1,Q2;
pair<long long,long long> p11,p12,p2;

void Clear(long long n){
	tot=0;sum=0;
	for(long long i=0;i<=n;i++){
		head[i]=val[i]=num[i]=tag[i]=0;
	}
	while(!Q1.empty())Q1.pop();
	while(!Q2.empty())Q2.pop();
}

void France(){
	long long n=read(),S=read(),u,v,w,op;
	Clear(n);
	for(long long i=1;i<n;i++){
		u=read();v=read();w=read();op=read();
		add(u,v,w,op);
	}
	dfs(1,0,0);
	for(long long i=2;i<=n;i++){
		if(tag[i]==1)Q1.push(make_pair(num[i]*(val[i]-val[i]/2),i));
		if(tag[i]==2)Q2.push(make_pair(num[i]*(val[i]-val[i]/2),i));
	}

	long long ans=0;

	if(!Q1.empty()){
		p11=Q1.top();Q1.pop();
		p12=Q1.top();Q1.push(p11);
	}else{
		p11=p12=make_pair(0,0);
	}

	if(!Q2.empty())p2=Q2.top();
	else p2=make_pair(0,0);
	while(sum>S){
		if(p11.first+p12.first<p2.first){

			ans+=2;
			sum-=p2.first;
			long long id=p2.second;
			val[id]/=2;
			Q2.push(make_pair(num[id]*(val[id]-val[id]/2),id));

			Q2.pop();
			p2=Q2.top();

		}else{
			ans++;
			sum-=p11.first;
			long long id=p11.second;
			val[id]/=2;
			Q1.push(make_pair(num[id]*(val[id]-val[id]/2),id));

			Q1.pop();
			p11=Q1.top();Q1.pop();
			p12=Q1.top();Q1.push(p11);
		}
	}
	printf("%lld\n",ans);

	return;
}

int main(){
	long long T=read();
	while(T--)France();
	return 0;
}


#include<bits/stdc++.h>
#define N 100009
using namespace std;

inline long long read(){
	long long x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f;
}

struct cow{
	long long v,w,next,op;
}E[N<<2];
long long head[N];

long long tot=0;
void add(long long u,long long v,long long w,long long op){
	E[++tot].v=v;E[tot].w=w;E[tot].op=op;
	E[tot].next=head[u];head[u]=tot;
	E[++tot].v=u;E[tot].w=w;E[tot].op=op;
	E[tot].next=head[v];head[v]=tot;
}

long long num[N],val[N],tag[N];
long long sum;

void dfs(long long u,long long fa,long long dis){
	bool flag=true;
	for(long long i=head[u];i;i=E[i].next){
		long long v=E[i].v;
		if(v==fa)continue;
		flag=false;
		dfs(v,u,dis+E[i].w);
		num[u]+=num[v];
		val[v]=E[i].w;
		tag[v]=E[i].op;
	}
	if(flag){
		sum+=dis;
		num[u]=1;
	}
}

priority_queue<pair<long long,long long> >Q1,Q2;
pair<long long,long long> p11,p12,p2;

void Clear(long long n){
	tot=0;sum=0;
	for(long long i=0;i<=n;i++){
		head[i]=val[i]=num[i]=tag[i]=0;
	}
	while(!Q1.empty())Q1.pop();
	while(!Q2.empty())Q2.pop();
}

void France(){
	long long n=read(),S=read(),u,v,w,op;
	Clear(n);
	for(long long i=1;i<n;i++){
		u=read();v=read();w=read();op=read();
		add(u,v,w,op);
	}
	dfs(1,0,0);
	for(long long i=2;i<=n;i++){
		if(tag[i]==1)Q1.push(make_pair(num[i]*(val[i]-val[i]/2),i));
		if(tag[i]==2)Q2.push(make_pair(num[i]*(val[i]-val[i]/2),i));
	}

	long long ans=0;

	p11=Q1.top();Q1.pop();
	p12=Q1.top();Q1.push(p11);
	p2=Q2.top();
	while(sum>S){
		if(p11.first+p12.first<p2.first){

			ans+=2;
			sum-=p2.first;
			long long id=p2.second;
			val[id]/=2;
			Q2.push(make_pair(num[id]*(val[id]-val[id]/2),id));

			Q2.pop();
			p2=Q2.top();

		}else{
			ans++;
			sum-=p11.first;
			long long id=p11.second;
			val[id]/=2;
			Q1.push(make_pair(num[id]*(val[id]-val[id]/2),id));

			Q1.pop();
			p11=Q1.top();Q1.pop();
			p12=Q1.top();Q1.push(p11);
		}
	}
	printf("%lld\n",ans);

	return;
}

int main(){
	long long T=read();
	while(T--)France();
	return 0;
}


#include<bits/stdc++.h>
#define N 100009
using namespace std;

inline long long read(){
	long long x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f;
}

struct cow{
	long long v,w,next,op;
}E[N<<2];
long long head[N];

long long tot=0;
void add(long long u,long long v,long long w,long long op){
	E[++tot].v=v;E[tot].w=w;E[tot].op=op;
	E[tot].next=head[u];head[u]=tot;
	E[++tot].v=u;E[tot].w=w;E[tot].op=op;
	E[tot].next=head[v];head[v]=tot;
}

long long num[N],val[N],tag[N];
long long sum;

void dfs(long long u,long long fa,long long dis){
	bool flag=true;
	for(long long i=head[u];i;i=E[i].next){
		long long v=E[i].v;
		if(v==fa)continue;
		flag=false;
		dfs(v,u,dis+E[i].w);
		num[u]+=num[v];
		val[v]=E[i].w;
		tag[v]=E[i].op;
	}
	if(flag){
		sum+=dis;
		num[u]=1;
	}
}

priority_queue<pair<long long,long long> >Q1,Q2;
pair<long long,long long> p11,p12,p2;

void Clear(long long n){
	tot=0;sum=0;
	for(long long i=0;i<=n;i++){
		head[i]=val[i]=num[i]=0;
	}
	while(!Q1.empty())Q1.pop();
	while(!Q2.empty())Q2.pop();
}

void France(){
	long long n=read(),S=read(),u,v,w,op;
	Clear(n);
	for(long long i=1;i<n;i++){
		u=read();v=read();w=read();op=read();
		add(u,v,w,op);
	}
	dfs(1,0,0);
	for(long long i=2;i<=n;i++){
		if(tag[i]==1)Q1.push(make_pair(num[i]*(val[i]-val[i]/2),i));
		if(tag[i]==2)Q2.push(make_pair(num[i]*(val[i]-val[i]/2),i));
	}

	long long ans=0;

	p11=Q1.top();Q1.pop();
	p12=Q1.top();Q1.push(p11);
	p2=Q2.top();
	while(sum>S){
		if(p11.first+p12.first<p2.first){

			ans+=2;
			sum-=p2.first;
			long long id=p2.second;
			val[id]/=2;
			Q2.push(make_pair(num[id]*(val[id]-val[id]/2),id));

			Q2.pop();
			p2=Q2.top();

		}else{
			ans++;
			sum-=p11.first;
			long long id=p11.second;
			val[id]/=2;
			Q1.push(make_pair(num[id]*(val[id]-val[id]/2),id));

			Q1.pop();
			p11=Q1.top();Q1.pop();
			p12=Q1.top();Q1.push(p11);
		}
	}
	printf("%lld\n",ans);

	return;
}

int main(){
	long long T=read();
	while(T--)France();
	return 0;
}


#include<bits/stdc++.h>
#define N 100009
using namespace std;

inline long long read(){
	long long x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f;
}

struct cow{
	long long v,w,next,op;
}E[N<<2];
long long head[N];

long long tot=0;
void add(long long u,long long v,long long w,long long op){
	E[++tot].v=v;E[tot].w=w;E[tot].op=op;
	E[tot].next=head[u];head[u]=tot;
	E[++tot].v=u;E[tot].w=w;E[tot].op=op;
	E[tot].next=head[v];head[v]=tot;
}

long long num[N],val[N],tag[N];
long long sum;

void dfs(long long u,long long fa,long long dis){
	bool flag=true;
	for(long long i=head[u];i;i=E[i].next){
		long long v=E[i].v;
		if(v==fa)continue;
		flag=false;
		dfs(v,u,dis+E[i].w);
		num[u]+=num[v];
		val[v]=E[i].w;
		tag[v]=E[i].op;
	}
	if(flag){
		sum+=dis;
		num[u]=1;
	}
}

priority_queue<pair<long long,long long> >Q1,Q2;
pair<long long,long long> p;

void Clear(long long n){
	tot=0;sum=0;
	for(long long i=0;i<=n;i++){
		head[i]=val[i]=num[i]=tag[i]=0;
	}
	while(!Q1.empty())Q1.pop();
	while(!Q2.empty())Q2.pop();
}

long long ans1[5000003],ans2[5000003];

void France(){
	long long n=read(),S=read(),u,v,w,op;
	Clear(n);
	for(long long i=1;i<n;i++){
		u=read();v=read();w=read();op=read();
		add(u,v,w,op);
	}
	dfs(1,0,0);
	for(long long i=2;i<=n;i++){
		if(tag[i]==1)Q1.push(make_pair(num[i]*(val[i]-val[i]/2),i));
		if(tag[i]==2)Q2.push(make_pair(num[i]*(val[i]-val[i]/2),i));
	}

	long long cnt1=0,cnt2=0,tmp,sum1=0,sum2=0;
	tmp=sum;
	while(tmp>S&&!Q1.empty()){
		p=Q1.top();Q1.pop();
		if(p.first==0)break;
		tmp-=p.first;cnt1++;
		sum1+=p.first;ans1[cnt1]=sum1;
		long long id=p.second;
		val[id]/=2;
		Q1.push(make_pair(num[id]*(val[id]-val[id]/2),id));
	}

	tmp=sum;
	while(tmp>S&&!Q2.empty()){
		p=Q2.top();Q2.pop();
		if(p.first==0)break;
		tmp-=p.first;cnt2++;
		sum2+=p.first;ans2[cnt2]=sum2;
		long long id=p.second;
		val[id]/=2;
		Q2.push(make_pair(num[id]*(val[id]-val[id]/2),id));
	}

	long long ans=1000000000000000;
	for(long long i=0;i<=cnt1;i++){
		for(long long j=0;j<=cnt2;j++){
			if(sum-ans1[i]-ans2[j]<=S){
				ans=min(ans,i+j+j);break;
			}
		}
	}

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

	return;
}

int main(){
	long long T=read();
	while(T--)France();
	return 0;
}


#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define MAXN 100005
typedef long long LL;
#define int LL
const int INF=0x7f7f7f7f;
typedef pair<LL,LL> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;if(s=='n'){x=-1;break;}s=getchar();}
	if(x<0)return ;
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
struct ming{
	int siz,val;
	bool operator < (const ming &rhs)const{
		return ceil(val/2.0)*siz<ceil(rhs.val/2.0)*rhs.siz;
	}
};
struct edge{int u,v,nxt,w,c;}e[MAXN<<1];
int tot,cnt,ans,head[MAXN],sz[MAXN],n,S,dep[MAXN];
priority_queue<ming>q1,q2;
void addEdge(int u,int v,int w,int c){e[++tot]=(edge){u,v,head[u],w,c};head[u]=tot;}
int dfs(int u,int fa){
	int cntt=0;dep[u]=dep[fa]+1;
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].v;if(v==fa)continue;
		dfs(v,u);cntt++;sz[u]+=sz[v];
	}
	if(!cntt)sz[u]=1;return sz[u];
}
signed main(){
	int t;read(t);
	while(t--){
		tot=cnt=ans=0;read(n);read(S);
		for(int i=1;i<=n;i++)head[i]=sz[i]=0;
		while(!q1.empty())q1.pop();
		while(!q2.empty())q2.pop();
		for(int i=1;i<n;i++){
			int u,v,w,c;read(u);read(v);read(w);read(c);
			addEdge(u,v,w,c);addEdge(v,u,w,c);
		}
		dfs(1,1);
		for(int i=1;i<=tot;i++){
			int u=e[i].u,v=e[i].v,w=e[i].w,c=e[i].c;
			if(dep[u]>dep[v])continue;ans+=sz[v]*w;
			if(c==1)q1.push((ming){sz[v],w});
			else q2.push((ming){sz[v],w});
		}
		while(ans>S){
			if(!q1.empty()&&ans-q1.top().siz*ceil(q1.top().val/2.0)<=S){cnt++;break;}
			ming qt1,qt2,qs1;qt1=qt2=qs1=(ming){0,0};
			if(!q1.empty())qt1=q1.top(),q1.pop();
			if(!q1.empty())qt2=q1.top();
			if(!q2.empty())qs1=q2.top();
			if(qt1.val/2*qt1.siz>=qt2.val*qt2.siz){
				if(qt1.siz*(ceil(qt1.val/2.0)+ceil((qt1.val/2)/2.0))<=qs1.siz*ceil(qs1.val/2.0)){
					ans-=qs1.siz*ceil(qs1.val/2.0);q1.push(qt1);q2.pop();
					if(qs1.val/2!=0)q2.push((ming){qs1.siz,qs1.val/2});cnt+=2;
				}
				else{
					ans-=qt1.siz*ceil(qt1.val/2.0);
					if(qt1.val/2!=0)q1.push((ming){qt1.siz,qt1.val/2});cnt++;
				}
			}
			else{
				if(qt1.siz*ceil(qt1.val/2.0)+qt2.siz*ceil(qt2.val/2.0)<=qs1.siz*ceil(qs1.val/2.0)){
					ans-=qs1.siz*ceil(qs1.val/2.0);q1.push(qt1);q2.pop();
					if(qs1.val/2)q2.push((ming){qs1.siz,qs1.val/2});cnt+=2;
				}
				else{
					ans-=qt1.siz*ceil(qt1.val/2.0);
					if(qt1.val/2)q1.push((ming){qt1.siz,qt1.val/2});cnt++;
				}
			}
		}
		printf("%lld\n",cnt);
	}
	return 0;
}


#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define MAXN 100005
typedef long long LL;
#define int LL
const int INF=0x7f7f7f7f;
typedef pair<LL,LL> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;if(s=='n'){x=-1;break;}s=getchar();}
	if(x<0)return ;
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
struct ming{
	int siz,val;
	bool operator < (const ming &rhs)const{
		return ceil(val/2.0)*siz<ceil(rhs.val/2.0)*rhs.siz;
	}
};
struct edge{int u,v,nxt,w,c;}e[MAXN<<1];
int tot,cnt,ans,head[MAXN],sz[MAXN],n,S,dep[MAXN];
priority_queue<ming>q1,q2;
void addEdge(int u,int v,int w,int c){e[++tot]=(edge){u,v,head[u],w,c};head[u]=tot;}
int dfs(int u,int fa){
	int cntt=0;dep[u]=dep[fa]+1;
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].v;if(v==fa)continue;
		dfs(v,u);cntt++;sz[u]+=sz[v];
	}
	if(!cntt)sz[u]=1;return sz[u];
}
signed main(){
	int t;read(t);
	while(t--){
		tot=cnt=ans=0;read(n);read(S);
		memset(sz,0,sizeof(sz));
		memset(head,0,sizeof(head));
		while(!q1.empty())q1.pop();
		while(!q2.empty())q2.pop();
		for(int i=1;i<n;i++){
			int u,v,w,c;read(u);read(v);read(w);read(c);
			addEdge(u,v,w,c);addEdge(v,u,w,c);
		}
		dfs(1,1);
		for(int i=1;i<=tot;i++){
			int u=e[i].u,v=e[i].v,w=e[i].w,c=e[i].c;
			if(dep[u]>dep[v])continue;ans+=sz[v]*w;
			if(c==1)q1.push((ming){sz[v],w});
			else q2.push((ming){sz[v],w});
		}
		while(ans>S){
			if(!q1.empty()&&ans-q1.top().siz*ceil(q1.top().val/2.0)<=S){cnt++;break;}
			ming qt1,qt2,qs1;qt1=qt2=qs1=(ming){0,0};
			if(!q1.empty())qt1=q1.top(),q1.pop();
			if(!q1.empty())qt2=q1.top();
			if(!q2.empty())qs1=q2.top();
			if(qt1.val/2*qt1.siz>=qt2.val*qt2.siz){
				if(qt1.siz*(ceil(qt1.val/2.0)+ceil((qt1.val/2)/2.0))<=qs1.siz*ceil(qs1.val/2.0)){
					ans-=qs1.siz*ceil(qs1.val/2.0);q1.push(qt1);q2.pop();
					if(qs1.val/2!=0)q2.push((ming){qs1.siz,qs1.val/2});cnt+=2;
				}
				else{
					ans-=qt1.siz*ceil(qt1.val/2.0);
					if(qt1.val/2!=0)q1.push((ming){qt1.siz,qt1.val/2});cnt++;
				}
			}
			else{
				if(qt1.siz*ceil(qt1.val/2.0)+qt2.siz*ceil(qt2.val/2.0)<=qs1.siz*ceil(qs1.val/2.0)){
					ans-=qs1.siz*ceil(qs1.val/2.0);q1.push(qt1);q2.pop();
					if(qs1.val/2)q2.push((ming){qs1.siz,qs1.val/2});cnt+=2;
				}
				else{
					ans-=qt1.siz*ceil(qt1.val/2.0);
					if(qt1.val/2)q1.push((ming){qt1.siz,qt1.val/2});cnt++;
				}
			}
		}
		printf("%lld\n",cnt);
	}
	return 0;
}


#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define MAXN 100005
typedef long long LL;
const int INF=0x7f7f7f7f;
typedef pair<LL,LL> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;if(s=='n'){x=-1;break;}s=getchar();}
	if(x<0)return ;
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
struct ming{
	int siz,val;
	bool operator < (const ming &rhs)const{
		return 1ll*ceil(val/2.0)*siz<1ll*ceil(rhs.val/2.0)*rhs.siz;
	}
};
struct edge{int u,v,nxt,w,c;}e[MAXN<<1];
int tot,cnt,head[MAXN],sz[MAXN],n,dep[MAXN];
LL ans,S;
priority_queue<ming>q1,q2;
void addEdge(int u,int v,int w,int c){e[++tot]=(edge){u,v,head[u],w,c};head[u]=tot;}
int dfs(int u,int fa){
	int cntt=0;dep[u]=dep[fa]+1;
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].v;if(v==fa)continue;
		dfs(v,u);cntt++;sz[u]+=sz[v];
	}
	if(!cntt)sz[u]=1;return sz[u];
}
signed main(){
	int t;read(t);
	while(t--){
		tot=cnt=ans=0;read(n);read(S);
		for(int i=1;i<=n;i++)head[i]=sz[i]=0;
		while(!q1.empty())q1.pop();
		while(!q2.empty())q2.pop();
		for(int i=1;i<n;i++){
			int u,v,w,c;read(u);read(v);read(w);read(c);
			addEdge(u,v,w,c);addEdge(v,u,w,c);
		}
		dfs(1,1);
		for(int i=1;i<=tot;i++){
			int u=e[i].u,v=e[i].v,w=e[i].w,c=e[i].c;
			if(dep[u]>dep[v])continue;ans+=1ll*sz[v]*w;
			if(c==1)q1.push((ming){sz[v],w});
			else q2.push((ming){sz[v],w});
		}
		while(ans>S){
			if(!q1.empty()&&ans-1ll*q1.top().siz*ceil(q1.top().val/2.0)<=S){cnt++;break;}
			ming qt1,qt2,qs1;qt1=qt2=qs1=(ming){0,0};
			if(!q1.empty())qt1=q1.top(),q1.pop();
			if(!q1.empty())qt2=q1.top();
			if(!q2.empty())qs1=q2.top();
			if(1ll*qt1.val/2*qt1.siz>=1ll*qt2.val*qt2.siz){
				if(1ll*qt1.siz*(ceil(qt1.val/2.0)+ceil((qt1.val/2)/2.0))<=1ll*qs1.siz*ceil(qs1.val/2.0)){
					ans-=1ll*qs1.siz*ceil(qs1.val/2.0);q1.push(qt1);q2.pop();
					if(qs1.val/2!=0)q2.push((ming){qs1.siz,qs1.val/2});cnt+=2;
				}
				else{
					ans-=1ll*qt1.siz*ceil(qt1.val/2.0);
					if(qt1.val/2!=0)q1.push((ming){qt1.siz,qt1.val/2});cnt++;
				}
			}
			else{
				if(1ll*qt1.siz*ceil(qt1.val/2.0)+1ll*qt2.siz*ceil(qt2.val/2.0)<=1ll*qs1.siz*ceil(qs1.val/2.0)){
					ans-=1ll*qs1.siz*ceil(qs1.val/2.0);q1.push(qt1);q2.pop();
					if(qs1.val/2)q2.push((ming){qs1.siz,qs1.val/2});cnt+=2;
				}
				else{
					ans-=1ll*qt1.siz*ceil(qt1.val/2.0);
					if(qt1.val/2)q1.push((ming){qt1.siz,qt1.val/2});cnt++;
				}
			}
		}
		printf("%d\n",cnt);
	}
	return 0;
}


#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define MAXN 100005
typedef long long LL;
const int INF=0x7f7f7f7f;
typedef pair<LL,LL> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;if(s=='n'){x=-1;break;}s=getchar();}
	if(x<0)return ;
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
struct ming{
	int siz,val;
	bool operator < (const ming &rhs)const{
		return 1ll*ceil(val/2.0)*siz<1ll*ceil(rhs.val/2.0)*rhs.siz;
	}
};
struct edge{int u,v,nxt,w,c;}e[MAXN<<1];
int tot,cnt,head[MAXN],sz[MAXN],n,dep[MAXN];
LL ans,S;
priority_queue<ming>q1,q2;
void addEdge(int u,int v,int w,int c){e[++tot]=(edge){u,v,head[u],w,c};head[u]=tot;}
int dfs(int u,int fa){
	int cntt=0;dep[u]=dep[fa]+1;
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].v;if(v==fa)continue;
		dfs(v,u);cntt++;sz[u]+=sz[v];
	}
	if(!cntt)sz[u]=1;return sz[u];
}
signed main(){
	int t;read(t);
	while(t--){
		tot=cnt=ans=0;read(n);read(S);
		for(int i=1;i<=n;i++)head[i]=sz[i]=0;
		while(!q1.empty())q1.pop();
		while(!q2.empty())q2.pop();
		for(int i=1;i<n;i++){
			int u,v,w,c;read(u);read(v);read(w);read(c);
			addEdge(u,v,w,c);addEdge(v,u,w,c);
		}
		dfs(1,1);
		for(int i=1;i<=tot;i++){
			int u=e[i].u,v=e[i].v,w=e[i].w,c=e[i].c;
			if(dep[u]>dep[v])continue;ans+=1ll*sz[v]*w;
			if(c==1)q1.push((ming){sz[v],w});
			else q2.push((ming){sz[v],w});
		}
		while(ans>S){
			if(!q1.empty()&&ans-1ll*q1.top().siz*ceil(q1.top().val/2.0)<=S){cnt++;break;}
			ming qt1,qt2,qs1;qt1=qt2=qs1=(ming){0,0};
			if(!q1.empty())qt1=q1.top(),q1.pop();
			if(!q1.empty())qt2=q1.top();
			if(!q2.empty())qs1=q2.top();
			if(1ll*qt1.val/2*qt1.siz>=1ll*qt2.val*qt2.siz){
				if(1ll*qt1.siz*(ceil(qt1.val/2.0)+ceil((qt1.val/2)/2.0))<=1ll*qs1.siz*ceil(qs1.val/2.0)){
					ans-=1ll*qs1.siz*ceil(qs1.val/2.0);q1.push(qt1);q2.pop();
					if(qs1.val/2!=0)q2.push((ming){qs1.siz,qs1.val/2});cnt+=2;
				}
				else{
					ans-=1ll*qt1.siz*ceil(qt1.val/2.0);
					if(qt1.val/2!=0)q1.push((ming){qt1.siz,qt1.val/2});cnt++;
				}
			}
			else{
				if(1ll*qt1.siz*ceil(qt1.val/2.0)+1ll*qt2.siz*ceil(qt2.val/2.0)<=1ll*qs1.siz*ceil(qs1.val/2.0)){
					ans-=1ll*qs1.siz*ceil(qs1.val/2.0);q1.push(qt1);q2.pop();
					if(qs1.val/2)q2.push((ming){qs1.siz,qs1.val/2});cnt+=2;
				}
				else{
					ans-=1ll*qt1.siz*ceil(qt1.val/2.0);
					if(qt1.val/2)q1.push((ming){qt1.siz,qt1.val/2});cnt++;
				}
			}
		}
		printf("%d\n",cnt);
	}
	return 0;
}


#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstring>
#include <ctime>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#define MP make_pair
#define ll long long
#define ld long double
#define null NULL
#define all(a) a.begin(), a.end()
#define forn(i, n) for (int i = 0; i < n; ++i)
#define sz(a) (int)a.size()
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
#define bitCount(a)  __builtin_popcount(a)
template<class T> int gmax(T &a, T b) { if (b > a) { a = b; return 1; } return 0; }
template<class T> int gmin(T &a, T b) { if (b < a) { a = b; return 1; } return 0; }
using namespace std;
const int INF = 0x3f3f3f3f;
string to_string(string s) { return '"' + s + '"'; }
string to_string(const char* s) { return to_string((string) s); }
string to_string(bool b) { return (b ? "true" : "false"); }
template <typename A, typename B>
string to_string(pair<A, B> p) { return "(" + to_string(p.first) + ", " + to_string(p.second) + ")"; }
template <typename A>
string to_string(A v) { bool first = true; string res = "{"; for (const auto &x : v) { if (!first) { res += ", "; } first = false; res += to_string(x); } res += "}"; return res; }
void debug_out() { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) { cerr << " " << to_string(H); debug_out(T...); }
#ifdef LOCAL
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif

const int N = 1e5 + 5;
struct Node{
    int fr, to, nx, dis, cost;
}E[N << 1];

int head[N]; int tot = 0;

void add(int fr, int to, int wei, int cost) {
    E[tot].to = to; E[tot].nx = head[fr]; E[tot].dis = wei; E[tot].cost = cost; head[fr] = tot ++;
}

vector<ll> dis_list_one;
vector<ll> dis_list_two;

ll ans = 0;

int dfs(int x, int pre, int dis, int cost) {
    int sons = 0;
    int leafs = 0;
    for(int i = head[x]; ~i; i = E[i].nx) {
        int to = E[i].to;
        if(to == pre) continue;
        leafs += dfs(to, x, E[i].dis, E[i].cost);
        sons ++;
    }

    if(sons == 0) leafs = 1;

    debug(x, dis, leafs, sons);

    int tmp = dis;
    ans += 1ll * dis * leafs;
    while(tmp) {
        if(cost == 1) dis_list_one.push_back( 1ll * (tmp - tmp / 2) * leafs) ;
        else if(cost == 2) dis_list_two.push_back( 1ll * (tmp - tmp / 2) * leafs) ;
        tmp /= 2;
    }

    return leafs;
}
int main() {
    int T;
    scanf("%d", &T);
    while(T --) {
        int n; ll S;
        scanf("%d %lld", &n, &S);
        for(int i = 0; i <= n; ++i) {
            head[i] = -1;
        }
        ans = 0;
        tot = 0;
        dis_list_one.clear();
        dis_list_two.clear();

        for(int i = 1; i < n; ++i) {
            int fr, to, wei, cost;
            scanf("%d %d %d %d", &fr, &to, &wei, &cost);
            add(fr, to, wei, cost);
            add(to, fr, wei, cost);
        }

        dfs(1, 1, 0, 0);

        sort(dis_list_one.begin(), dis_list_one.end(), [](ll x, ll y) {return x > y; });
        sort(dis_list_two.begin(), dis_list_two.end(), [](ll x, ll y) {return x > y; });

        int result = INF;
        debug(ans);
        if(ans <= S) {
            printf("0\n");
            continue;
        }

        for(int i = 1, len = dis_list_one.size(); i < len; ++i) {
            dis_list_one[i] += dis_list_one[i - 1];
        }

        for(int i = 1, len = dis_list_two.size(); i < len; ++i) {
            dis_list_two[i] += dis_list_two[i - 1];
        }

        for(int i = 0, len = dis_list_one.size(); i < len; ++i) {
            ll tt = ans - dis_list_one[i] - S;
            if(tt <= 0) {
                result = min(result, i + 1);
                break;
            }

            int pos = lower_bound(dis_list_two.begin(), dis_list_two.end(), tt) - dis_list_two.begin();

            if(pos != dis_list_two.size()) {
                result = min(result, i + 1 + 2 * (pos + 1));
            }
        }

        int pos = lower_bound(dis_list_two.begin(), dis_list_two.end(), ans - S) - dis_list_two.begin();

        if(pos != dis_list_two.size()) {
            result = min(result, 2 * (pos + 1));
        }

        printf("%d\n", result);
    }
    return 0;
}

/*

100
5 50
1 3 100
1 5 10
2 3 123
5 4 55

*/


#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstring>
#include <ctime>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#define MP make_pair
#define ll long long
#define ld long double
#define null NULL
#define all(a) a.begin(), a.end()
#define forn(i, n) for (int i = 0; i < n; ++i)
#define sz(a) (int)a.size()
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
#define bitCount(a)  __builtin_popcount(a)
template<class T> int gmax(T &a, T b) { if (b > a) { a = b; return 1; } return 0; }
template<class T> int gmin(T &a, T b) { if (b < a) { a = b; return 1; } return 0; }
using namespace std;
const int INF = 0x3f3f3f3f;
string to_string(string s) { return '"' + s + '"'; }
string to_string(const char* s) { return to_string((string) s); }
string to_string(bool b) { return (b ? "true" : "false"); }
template <typename A, typename B>
string to_string(pair<A, B> p) { return "(" + to_string(p.first) + ", " + to_string(p.second) + ")"; }
template <typename A>
string to_string(A v) { bool first = true; string res = "{"; for (const auto &x : v) { if (!first) { res += ", "; } first = false; res += to_string(x); } res += "}"; return res; }
void debug_out() { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) { cerr << " " << to_string(H); debug_out(T...); }
#ifdef LOCAL
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif

const int N = 1e5 + 5;
struct Node{
    int fr, to, nx, dis, cost;
}E[N << 1];

int head[N]; int tot = 0;

void add(int fr, int to, int wei, int cost) {
    E[tot].to = to; E[tot].nx = head[fr]; E[tot].dis = wei; E[tot].cost = cost; head[fr] = tot ++;
}

vector<ll> dis_list_one;
vector<ll> dis_list_two;

ll ans = 0;

int dfs(int x, int pre, int dis, int cost) {
    int sons = 0;
    int leafs = 0;
    for(int i = head[x]; ~i; i = E[i].nx) {
        int to = E[i].to;
        if(to == pre) continue;
        leafs += dfs(to, x, E[i].dis, E[i].cost);
        sons ++;
    }

    if(sons == 0) leafs = 1;

    debug(x, dis, leafs, sons);

    int tmp = dis;
    ans += 1ll * dis * leafs;
    while(tmp) {
        if(cost == 1) dis_list_one.push_back( 1ll * (tmp - tmp / 2) * leafs) ;
        else if(cost == 2) dis_list_two.push_back( 1ll * (tmp - tmp / 2) * leafs) ;
        tmp /= 2;
    }

    return leafs;
}
int main() {
    int T;
    scanf("%d", &T);
    while(T --) {
        int n, S;
        scanf("%d %lld", &n, &S);
        for(int i = 0; i <= n; ++i) {
            head[i] = -1;
        }
        ans = 0;
        tot = 0;
        dis_list_one.clear();
        dis_list_two.clear();

        for(int i = 1; i < n; ++i) {
            int fr, to, wei, cost;
            scanf("%d %d %d %d", &fr, &to, &wei, &cost);
            add(fr, to, wei, cost);
            add(to, fr, wei, cost);
        }

        dfs(1, 1, 0, 0);

        sort(dis_list_one.begin(), dis_list_one.end(), [](ll x, ll y) {return x > y; });
        sort(dis_list_two.begin(), dis_list_two.end(), [](ll x, ll y) {return x > y; });

        int result = INF;
        debug(ans);
        if(ans <= S) {
            printf("0\n");
            continue;
        }

        for(int i = 1, len = dis_list_one.size(); i < len; ++i) {
            dis_list_one[i] += dis_list_one[i - 1];
        }

        for(int i = 1, len = dis_list_two.size(); i < len; ++i) {
            dis_list_two[i] += dis_list_two[i - 1];
        }

        for(int i = 0, len = dis_list_one.size(); i < len; ++i) {
            ll tt = ans - dis_list_one[i] - S;
            if(tt <= 0) {
                result = min(result, i + 1);
                break;
            }

            int pos = lower_bound(dis_list_two.begin(), dis_list_two.end(), tt) - dis_list_two.begin();

            if(pos != dis_list_two.size()) {
                result = min(result, i + 1 + 2 * (pos + 1));
            }
        }

        int pos = lower_bound(dis_list_two.begin(), dis_list_two.end(), ans - S) - dis_list_two.begin();

        if(pos != dis_list_two.size()) {
            result = min(result, 2 * (pos + 1));
        }

        printf("%d\n", result);
    }
    return 0;
}

/*

100
5 50
1 3 100
1 5 10
2 3 123
5 4 55

*/


#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstring>
#include <ctime>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#define MP make_pair
#define ll long long
#define ld long double
#define null NULL
#define all(a) a.begin(), a.end()
#define forn(i, n) for (int i = 0; i < n; ++i)
#define sz(a) (int)a.size()
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
#define bitCount(a)  __builtin_popcount(a)
template<class T> int gmax(T &a, T b) { if (b > a) { a = b; return 1; } return 0; }
template<class T> int gmin(T &a, T b) { if (b < a) { a = b; return 1; } return 0; }
using namespace std;
const int INF = 0x3f3f3f3f;
string to_string(string s) { return '"' + s + '"'; }
string to_string(const char* s) { return to_string((string) s); }
string to_string(bool b) { return (b ? "true" : "false"); }
template <typename A, typename B>
string to_string(pair<A, B> p) { return "(" + to_string(p.first) + ", " + to_string(p.second) + ")"; }
template <typename A>
string to_string(A v) { bool first = true; string res = "{"; for (const auto &x : v) { if (!first) { res += ", "; } first = false; res += to_string(x); } res += "}"; return res; }
void debug_out() { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) { cerr << " " << to_string(H); debug_out(T...); }
#ifdef LOCAL
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif

const int N = 1e5 + 5;
struct Node{
    int fr, to, nx, dis, cost;
}E[N << 1];

int head[N]; int tot = 0;

void add(int fr, int to, int wei, int cost) {
    E[tot].to = to; E[tot].nx = head[fr]; E[tot].dis = wei; E[tot].cost = cost; head[fr] = tot ++;
}

vector<ll> dis_list_one;
vector<ll> dis_list_two;

ll ans = 0;

int dfs(int x, int pre, int dis, int cost) {
    int sons = 0;
    int leafs = 0;
    for(int i = head[x]; ~i; i = E[i].nx) {
        int to = E[i].to;
        if(to == pre) continue;
        leafs += dfs(to, x, E[i].dis, E[i].cost);
        sons ++;
    }

    if(sons == 0) leafs = 1;

    debug(x, dis, leafs, sons);

    int tmp = dis;
    ans += 1ll * dis * leafs;
    while(tmp) {
        if(cost == 1) dis_list_one.push_back( 1ll * (tmp - tmp / 2) * leafs) ;
        else if(cost == 2) dis_list_two.push_back( 1ll * (tmp - tmp / 2) * leafs) ;
        tmp /= 2;
    }

    return leafs;
}
int main() {
    int T;
    scanf("%d", &T);
    while(T --) {
        int n, S;
        scanf("%d %d", &n, &S);
        for(int i = 0; i <= n; ++i) {
            head[i] = -1;
        }
        ans = 0;
        tot = 0;
        dis_list_one.clear();
        dis_list_two.clear();

        for(int i = 1; i < n; ++i) {
            int fr, to, wei, cost;
            scanf("%d %d %d %d", &fr, &to, &wei, &cost);
            add(fr, to, wei, cost);
            add(to, fr, wei, cost);
        }

        dfs(1, 1, 0, 0);

        sort(dis_list_one.begin(), dis_list_one.end(), [](ll x, ll y) {return x > y; });
        sort(dis_list_two.begin(), dis_list_two.end(), [](ll x, ll y) {return x > y; });

        int result = INF;
        debug(ans);
        if(ans <= S) {
            printf("0\n");
            continue;
        }

        for(int i = 1, len = dis_list_one.size(); i < len; ++i) {
            dis_list_one[i] += dis_list_one[i - 1];
        }

        for(int i = 1, len = dis_list_two.size(); i < len; ++i) {
            dis_list_two[i] += dis_list_two[i - 1];
        }

        for(int i = 0, len = dis_list_one.size(); i < len; ++i) {
            ll tt = ans - dis_list_one[i] - S;
            if(tt <= 0) {
                result = min(result, i + 1);
                continue;
            }

            int pos = lower_bound(dis_list_two.begin(), dis_list_two.end(), tt) - dis_list_two.begin();

            if(pos != dis_list_two.size()) {
                result = min(result, i + 1 + 2 * (pos + 1));
            }
        }

        int pos = lower_bound(dis_list_two.begin(), dis_list_two.end(), ans - S) - dis_list_two.begin();

        if(pos != dis_list_two.size()) {
            result = min(result, 2 * (pos + 1));
        }

        printf("%d\n", result);
    }
    return 0;
}

/*

100
5 50
1 3 100
1 5 10
2 3 123
5 4 55

*/


#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstring>
#include <ctime>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#define MP make_pair
#define ll long long
#define ld long double
#define null NULL
#define all(a) a.begin(), a.end()
#define forn(i, n) for (int i = 0; i < n; ++i)
#define sz(a) (int)a.size()
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
#define bitCount(a)  __builtin_popcount(a)
template<class T> int gmax(T &a, T b) { if (b > a) { a = b; return 1; } return 0; }
template<class T> int gmin(T &a, T b) { if (b < a) { a = b; return 1; } return 0; }
using namespace std;
const int INF = 0x3f3f3f3f;
string to_string(string s) { return '"' + s + '"'; }
string to_string(const char* s) { return to_string((string) s); }
string to_string(bool b) { return (b ? "true" : "false"); }
template <typename A, typename B>
string to_string(pair<A, B> p) { return "(" + to_string(p.first) + ", " + to_string(p.second) + ")"; }
template <typename A>
string to_string(A v) { bool first = true; string res = "{"; for (const auto &x : v) { if (!first) { res += ", "; } first = false; res += to_string(x); } res += "}"; return res; }
void debug_out() { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) { cerr << " " << to_string(H); debug_out(T...); }
#ifdef LOCAL
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif

const int N = 1e5 + 5;
struct Node{
    int fr, to, nx, dis, cost;
}E[N << 1];

int head[N]; int tot = 0;

void add(int fr, int to, int wei, int cost) {
    E[tot].to = to; E[tot].nx = head[fr]; E[tot].dis = wei; E[tot].cost = cost; head[fr] = tot ++;
}

vector<ll> dis_list_one;
vector<ll> dis_list_two;

ll ans = 0;

int dfs(int x, int pre, int dis, int cost) {
    int sons = 0;
    int leafs = 0;
    for(int i = head[x]; ~i; i = E[i].nx) {
        int to = E[i].to;
        if(to == pre) continue;
        leafs += dfs(to, x, E[i].dis, E[i].cost);
        sons ++;
    }

    if(sons == 0) leafs = 1;

    debug(x, dis, leafs, sons);

    int tmp = dis;
    ans += 1ll * dis * leafs;
    while(tmp) {
        if(cost == 1) dis_list_one.push_back( 1ll * (tmp - tmp / 2) * leafs) ;
        else if(cost == 2) dis_list_two.push_back( 1ll * (tmp - tmp / 2) * leafs) ;
        tmp /= 2;
    }

    return leafs;
}
int main() {
    int T;
    scanf("%d", &T);
    while(T --) {
        int n, S;
        scanf("%d %d", &n, &S);
        for(int i = 0; i <= n; ++i) {
            head[i] = -1;
        }
        ans = 0;
        tot = 0;
        dis_list_one.clear();
        dis_list_two.clear();

        for(int i = 1; i < n; ++i) {
            int fr, to, wei, cost;
            scanf("%d %d %d %d", &fr, &to, &wei, &cost);
            add(fr, to, wei, cost);
            add(to, fr, wei, cost);
        }

        dfs(1, 1, 0, 0);

        sort(dis_list_one.begin(), dis_list_one.end(), [](int x, int y) {return x > y; });
        sort(dis_list_two.begin(), dis_list_two.end(), [](int x, int y) {return x > y; });

        int result = INF;
        debug(ans);
        if(ans <= S) {
            printf("0\n");
            continue;
        }

        for(int i = 1, len = dis_list_one.size(); i < len; ++i) {
            dis_list_one[i] += dis_list_one[i - 1];
        }

        for(int i = 1, len = dis_list_two.size(); i < len; ++i) {
            dis_list_two[i] += dis_list_two[i - 1];
        }

        for(int i = 0, len = dis_list_one.size(); i < len; ++i) {
            ll tt = ans - dis_list_one[i] - S;
            if(tt <= 0) {
                result = min(result, i + 1);
                continue;
            }

            int pos = lower_bound(dis_list_two.begin(), dis_list_two.end(), tt) - dis_list_two.begin();

            if(pos != dis_list_two.size()) {
                result = min(result, i + 1 + 2 * (pos + 1));
            }
        }

        int pos = lower_bound(dis_list_two.begin(), dis_list_two.end(), ans - S) - dis_list_two.begin();

        if(pos != dis_list_two.size()) {
            result = min(result, 2 * (pos + 1));
        }

        printf("%d\n", result);
    }
    return 0;
}

/*

100
5 50
1 3 100
1 5 10
2 3 123
5 4 55

*/


//
//  E.cpp
//  ACM Coding
//
//  Created by Code_Bear on 2020/11/10
//  Copyright © 2020 Code_Bear. All rights reserved.
//

#include <algorithm>
#include <cstdio>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <vector>
using namespace std;
typedef long long ll;
const int INF = 1e18 + 7;
const int maxn = 200000 + 5;

class Edge {
 public:
  int u, v, w, c, leaf;
  Edge() {}
  Edge(int _u, int _v, int _w, int _c, int _leaf)
      : u(_u), v(_v), w(_w), c(_c), leaf(_leaf) {}
};

vector<int> edges[maxn];
Edge elist[maxn];
bool vis[maxn];

int bfs(int root) {
  vis[root] = true;
  int leaf = 0;
  for (int i = 0; i < edges[root].size(); ++i) {
    int cnt = edges[root][i];
    int u = elist[cnt].u;
    int v = elist[cnt].v;
    int children = u == root ? v : u;
    if (vis[children]) continue;
    elist[cnt].leaf = bfs(children);
    leaf += elist[cnt].leaf;
  }
  vis[root] = false;
  return leaf == 0 ? 1 : leaf;
}

int t, n;
ll s;

int main() {
  cin >> t;
  while (t--) {
    cin >> n >> s;
    for (int i = 0; i <= n; ++i) {
      edges[i].clear();
      vis[i] = false;
    }
    for (int i = 0; i < n - 1; ++i) {
      int v, u, w, c;
      cin >> v >> u >> w >> c;
      edges[v].push_back(i);
      edges[u].push_back(i);
      elist[i] = Edge(v, u, w, c, 0);
    }
    bfs(1);
    vector<ll> one, two;
    ll sum = 0;
    // for (int i = 0; i < n - 1; ++i) {
    //   cout << elist[i].v << ' ' << elist[i].u << " " << elist[i].w << " "
    //        << elist[i].c << " " << elist[i].leaf << endl;
    // }
    for (int i = 0; i < n - 1; ++i) {
      sum += elist[i].leaf * elist[i].w;
      while (true) {
        if (elist[i].w == 0) break;
        ll w1 = elist[i].w, w2 = w1 / 2;
        ll cost = elist[i].leaf * (w1 - w2);
        if (elist[i].c == 1)
          one.push_back(cost);
        else
          two.push_back(cost);
        elist[i].w = w2;
      }
    }
    if (sum <= s) {
      cout << 0 << endl;
      continue;
    }
    sort(one.begin(), one.end(), greater<ll>());
    sort(two.begin(), two.end(), greater<ll>());
    for (int i = 1; i < one.size(); ++i) one[i] += one[i - 1];
    for (int i = 1; i < two.size(); ++i) two[i] += two[i - 1];
    one.insert(one.begin(), 0);
    two.insert(two.begin(), 0);
    // for (int i = 0; i < one.size(); ++i) {
    //   if (i) cout << " ";
    //   cout << one[i];
    // }
    // cout << endl;
    ll ans = INF;
    for (int i = 0; i < one.size(); ++i) {
      ll cost = sum - s - one[i];
      ll iter = lower_bound(two.begin(), two.end(), cost) - two.begin();
      if (iter > two.size()) continue;
      if (one[i] + two[iter] < sum - s) continue;
      // cout << one[i] << " " << two[iter] << " " << i << " " << iter << endl;
      ans = min(ans, i + iter * 2ll);
    }
    cout << ans << endl;
  }

  return 0;
}


t = int(input())
for _ in range(t):
    p, f = list(map(int, input().split()))
    ts, tw = list(map(int, input().split()))
    s, w = list(map(int, input().split()))
    an = 0
    for i in range(min(p // s, ts) + 1):
        ans = i
        ans += min((p - i * s) // w, tw)
        for j in range(ts - i + 1):
            b = j
            b += min((f - j * s) // w, tw - (p - i * s) // w)
            an = max(ans + b, an)
    print(an)


t = int(input())
for _ in range(t):
    p, f = list(map(int, input().split()))
    ts, tw = list(map(int, input().split()))
    s, w = list(map(int, input().split()))
    if s > w:
        w, s = s, w
        tw, ts = ts, tw
    ans = 0
    for i in range(min(p // s, ts) + 1):
        a = i
        b = min((p - i * s) // w, tw)
        c = min(f // s, ts - i)
        d = min((f - c * s) // w, tw - b)
        ans = max(a + b + c + d, ans)
    print(ans)


t = int(input())
for _ in range(t):
    p, f = list(map(int, input().split()))
    ts, tw = list(map(int, input().split()))
    s, w = list(map(int, input().split()))
    ans = 0
    for i in range(min(p // s, ts) + 1):
        a = i
        a += min((p - i * s) // w, tw)
        for j in range(min(ts - i, f // s) + 1):
            b = j
            b += min((f - j * s) // w,  tw - min((p - i * s) // w, tw))
            ans = max(a + b, ans)
    print(ans)


for _ in range(int(input())):
    p, f = map(int, input().split())
    cnts, cntw = map(int, input().split())
    s, w = map(int, input().split())
    if s > w:
        s, w = w, s
        cntw, cnts = cnts, cntw
    kek = p // s + f // s
    if kek <= cnts:
        print(kek)
    else:
        ans = cnts
        for sk in range(cnts+1):
            p2, f2 = p, f
            p2 -= sk*s
            f2 -= (cnts-sk)*s
            if p2 >= 0 and f2 >= 0:
                ans = max(ans, cnts + p2 // w + f2 // w)
        ans = min(ans, cnts + cntw)
        print(ans)


scan = lambda: map(int, input().split())

for _ in range(int(input())):
    f, p = scan()   # you,  patner
    cnt_s, cnt_w = scan()  # swords, axe
    s, w = scan()  # s_weight, ax_weight
    ans = -1
    s, w, cnt_s, cnt_w = (w, s, cnt_w, cnt_s) if s > w else (s, w, cnt_s, cnt_w)
    for i in range(cnt_s + 1):

        swp =i
        swf = min(cnt_s-swp, (f//s))
        axwp = min(cnt_w, (p-swp*s)//w)
        axwf = min(cnt_w-axwp, (f-s*swf)//w)
        ans = max(ans, swp + swf + axwp + axwf)
    print(ans)


scan = lambda: map(int, input().split())

for _ in range(int(input())):
    f, p = scan()   # you,  patner
    cnt_s, cnt_w = scan()  # swords, axe
    s, w = scan()  # s_weight, ax_weight
    ans = -1
    s, w, cnt_s, cnt_w = (w, s, cnt_w, cnt_s) if s > w else (s, w, cnt_s, cnt_w)
    for i in range(cnt_s + 1):
        if i*s>p:
            break
        swp =i
        swf = min(cnt_s-swp, (f//s))
        axwp = min(cnt_w, (p-swp*s)//w)
        axwf = min(cnt_w-axwp, (f-s*swf)//w)
        ans = max(ans, swp + swf + axwp + axwf)
    print(ans)


t=int(input())
while(t):
    t-=1
    p,f=map(int,input().split())
    cs,cw=map(int,input().split())
    s,w=map(int,input().split())
    ans=0
    for n1 in range(cs+1):

        n2=min( int(( (p-s*n1) /w )) ,cw)
        cs1 =cs-n1
        cw1=cw-n2

        if(s > w):
            s,w,cs1,cw1=w,s,cw1,cs1

        m1,m2=0,0

        if(f >= s*cs1):
            m1=cs1
            m2=min(int((f-s*cs1)/w),cw1)
        else:
            m1=int(f/s)
            m2=0

        ans=max(ans,n1+n2+m1+m2)
    print(ans)


t=int(input())

while(t):
    t-=1
    p,f=map(int,input().split())
    cs,cw=map(int,input().split())
    s,w=map(int,input().split())
    ans=0

    if (s > w):
        s, w = w, s
        cs,cw = cw,cs

    for n1 in range(cs+1):

        if(n1*s > p):
            break

        n2=min(  (p-s*n1)//w  , cw)

        cs1 =cs-n1
        cw1=cw-n2

        m1,m2=0,0

        if(f > s*cs1):
            m1=cs1
            m2=min((f - s*cs1)//w,cw1)
        else:
            m1=f//s
            m2=0

        ans=max(ans,n1+n2+m1+m2)

    print(ans)