#include <stdio.h>
#include <math.h>

static char stdfile[] = "c.in";

void doTestCase( FILE* );

int main( int argc, char** argv ) {
    char* filename;
    if( argc < 2 )
        filename = stdfile;
    else
        filename = argv[1];
    FILE* f = stdin;//fopen( filename, "r" );
    int n = 0;
    fscanf( f, "%d", &n );
    while( n-- ) {
        doTestCase( f );
    }
    fclose( f );
    return 0;
}

typedef struct {
    double min;
    double max;
} Ramp;

void doTestCase( FILE* f ) {
Ramp ramps[10000];
float solved[10000];
int sortedmin[10000];
int sortedmax[10000];
    /* Read, keep track of minmin, minmax, maxmin and maxmax, keep a sorted list for min and max */
    int r;
    fscanf( f, "%d", &r );
    int i, j;
    long long m;
    fscanf( f, "%lld", &m );
    int minmin = 0;
    int maxmax = 0;
    int minmax = 0;
    int maxmin = 0;
    float min, max;
    int low, high, mid;
    for( i = 0; i < r; i++ ) {
        fscanf( f, "%f %f", &min, &max );
        ramps[i].min = min;
        ramps[i].max = max;
        if( ramps[i].min < ramps[minmin].min )
            minmin = i;
        if( ramps[i].min > ramps[maxmin].min )
            maxmin = i;
        if( ramps[i].max < ramps[minmax].max )
            minmax = i;
        if( ramps[i].max > ramps[maxmax].max )
            maxmax = i;
        low = 0;
        high = i;
        while( high > low ) {
            mid = ( ( high - low ) / 2 ) + low;
            if( ramps[sortedmin[mid]].min < min )
                low = mid + 1;
            else if( ramps[sortedmin[mid]].min > min )
                high = mid;
            else {
                high = mid;
                break;
            }
        }
        for( j = i; j > high; j-- )
            sortedmin[j] = sortedmin[j-1];
        sortedmin[high] = i;
        low = 0;
        high = i;
        while( high > low ) {
            mid = ( ( high - low ) / 2 ) + low;
            if( ramps[sortedmax[mid]].max < max )
                low = mid + 1;
            else if( ramps[sortedmax[mid]].max > max )
                high = mid;
            else {
                high = mid;
                break;
            }
        }
        for( j = i; j > high; j-- )
            sortedmax[j] = sortedmax[j-1];
        sortedmax[high] = i;
    }
    /* Solve max */
    double inhoud = 0;
    int origminmin = minmin;
    // If minmin and maxmax are equal, we need another minmin
    if( minmin == maxmax ) {
        int newminmin = 0;
        if( 0 == maxmax )
            newminmin = 1;
        for( i = 0; i < r; i++ ) {
            solved[i] = ramps[i].min;
            inhoud += solved[i] * solved[i] * 2;
            if( i != maxmax && ramps[i].min < ramps[newminmin].min )
                newminmin = i;
        }
        minmin = newminmin;
    }
    else {
        for( i = 0; i < r; i++ ) {
            solved[i] = ramps[i].min;
            inhoud += solved[i] * solved[i] * 2;
        }
    }
    inhoud -= solved[maxmax] * solved[maxmax] * 2;
    solved[maxmax] = ramps[maxmax].max;
    inhoud += solved[maxmax] * solved[maxmax] * 2;
    if( inhoud > m ) {
        solved[maxmax] = sqrt((m - (inhoud - (solved[maxmax] * solved[maxmax] * 2))) / 2);
    }
    else {
        for( i = 0; i < r; i++ ) {
            if( i == minmin || i == maxmax )
                continue;
            inhoud += ramps[i].max * ramps[i].max * 2 - solved[i] * solved[i] * 2;
            if( inhoud > m ) {
                break;
            }
        }
        if( inhoud < m ) {
            solved[minmin] = sqrt((m - (inhoud - (solved[minmin] * solved[minmin] * 2))) / 2);
        }
    }
    double currmin = solved[0];
    double currmax = solved[0];
    for( i = 1; i < r; i++ ) {
        if( currmin > solved[i] )
            currmin = solved[i];
        if( currmax < solved[i] )
            currmax = solved[i];
    }
    float maxDiff = currmax - currmin;
    if( origminmin == maxmax ) {
        /* minmin == maxmax, a second heuristic choice exists, so let's calculate that as well */
        inhoud = 0;
        minmin = origminmin;
        int newmaxmax = 0;
        if( maxmax == 0 )
            newmaxmax = 1;
        for( i = 0; i < r; i++ ) {
            solved[i] = ramps[i].min;
            inhoud += solved[i] * solved[i] * 2;
            if( i != maxmax && ramps[i].max > ramps[newmaxmax].max )
                newmaxmax = i;
        }
        maxmax = newmaxmax;
        inhoud -= solved[maxmax] * solved[maxmax] * 2;
        solved[maxmax] = ramps[maxmax].max;
        inhoud += solved[maxmax] * solved[maxmax] * 2;
        if( inhoud > m ) {
            solved[maxmax] = sqrt((m - (inhoud - (solved[maxmax] * solved[maxmax] * 2))) / 2);
        }
        else {
            for( i = 0; i < r; i++ ) {
                if( i == minmin || i == maxmax )
                    continue;
                inhoud += ramps[i].max * ramps[i].max * 2 - solved[i] * solved[i] * 2;
                if( inhoud > m ) {
                    break;
                }
            }
            if( inhoud < m ) {
                solved[minmin] = sqrt((m - (inhoud - (solved[minmin] * solved[minmin] * 2))) / 2);
            }
        }
        currmin = solved[0];
        currmax = solved[0];
        for( i = 1; i < r; i++ ) {
            if( currmin > solved[i] )
                currmin = solved[i];
            if( currmax < solved[i] )
                currmax = solved[i];
        }
        float maxDiff2 = currmax - currmin;
        if( maxDiff2 > maxDiff )
            maxDiff = maxDiff2;
        maxmax = minmin;
    }
    /* Solve min */
    // Algorithm:
    // Put everything as close to avg as possible
    // Then start pushing everything up or down, away from avg
    // - Start with everything that's avg and has max > avg (or min < avg when pushing down)
    // - Define the new value as the next avg and repeat until the needed volume is found
    //
    // Pushing up:
    // - Keep track in sortedmax where the smallest max > avg is
    // - Keep track in sortedmin where the smallest min > avg is
    // - Divide the remainder of the concrete over the ramps to be pushed and calculate their equallyDividedHeight
    // - Push (number of max > avg)-(number of min > avg) to MIN(smallest max > avg, smallest min > avg, equallyDividedHeight)
    //
    // Pushing down:
    // - Keep track in sortedmin where biggest min < avg is
    // - Keep track in sortedmax where biggest max < avg is
    // - Divide the remainder of the difference over the ramps to be pushed and calculate their equallyDividedHeight
    // - Push (number of min < avg)-)number of max < avg) to MAX(biggest min < avg, biggest max < avg, equallDividedHeight)
    inhoud = m;
    double avg = sqrt(((float)m / r)/2);
    double avgSq = avg * avg * 2;
    int maxminbelowavg = minmin;
    int minmaxaboveavg = maxmax;
    int minminaboveavg = maxmin;
    int maxmaxbelowavg = minmax;
    for( i = 0; i < r; i++ ) {
        solved[i] = avg;
        if( avg < ramps[i].min ) {
            solved[i] = ramps[i].min;
            inhoud += solved[i] * solved[i] * 2 - avgSq;
            if( ramps[minminaboveavg].min > ramps[i].min )
                minminaboveavg = i;
        }
        else if( ramps[maxminbelowavg].min < ramps[i].min )
            maxminbelowavg = i;
        if( avg > ramps[i].max ) {
            solved[i] = ramps[i].max;
            inhoud += solved[i] * solved[i] * 2 - avgSq;
            if( ramps[maxmaxbelowavg].max < ramps[i].max )
                maxmaxbelowavg = i;
        }
        else if( ramps[minmaxaboveavg].max > ramps[i].max )
            minmaxaboveavg = i;
    }
    if( inhoud > m ) {
        int minindex = 0;
        while( sortedmin[minindex] != maxminbelowavg )
            minindex++;
        minindex++;
        while( minindex < r && ramps[sortedmin[minindex]].min == ramps[maxminbelowavg].min )
            minindex++;
        minindex--;
        int maxindex = 0;
        while( sortedmax[maxindex] != maxmaxbelowavg )
            maxindex++;
        maxindex++;
        while( maxindex < r && ramps[sortedmax[maxindex]].max == ramps[maxmaxbelowavg].max )
            maxindex++;
        maxindex--;
        if( ramps[sortedmax[maxindex]].max >= avg )
            maxindex = -1;
        double newavg;
        int index;
        bool ismax;
        do {
            if( minindex < 0 || maxindex < -1 ) {
                fprintf( stderr, "Insanity!\n" );
                ((Ramp*)0)->min = 0;
            }
            index = sortedmin[minindex];
            newavg = ramps[sortedmin[minindex]].min;
            ismax = 0;
            if( maxindex >= 0 && ramps[sortedmax[maxindex]].max > newavg ) {
                newavg = ramps[sortedmax[maxindex]].max;
                index = sortedmax[maxindex];
                ismax = 1;
            }
            inhoud += ((minindex+1)-(maxindex+1)) * ( newavg * newavg - avg * avg ) * 2;
            solved[index] = newavg;
            if( inhoud < m ) {
                inhoud -= ((minindex+1)-(maxindex+1)) * newavg * newavg * 2;
                solved[index] = sqrt((((float)(m - inhoud)) / ((minindex+1)-(maxindex+1))) / 2);
                inhoud = m;
            }
            if( ismax )
                maxindex--;
            else
                minindex--;
            avg = newavg;
        } while( inhoud > m );
    }
    else if( inhoud < m ) {
        int maxindex = 0;
        while( sortedmax[maxindex] != minmaxaboveavg )
            maxindex++;
        maxindex--;
        while( maxindex >= 0 && ramps[sortedmax[maxindex]].max == ramps[minmaxaboveavg].max )
            maxindex--;
        maxindex++;
        int minindex = 0;
        while( sortedmin[minindex] != minminaboveavg )
            minindex++;
        minindex--;
        while( minindex >= 0 && ramps[sortedmin[minindex]].min == ramps[minminaboveavg].min )
            minindex--;
        minindex++;
        if( ramps[sortedmin[minindex]].min <= avg )
            minindex = r;
        double newavg;
        int index;
        bool ismin;
        do {
            if( minindex > r || maxindex >= r ) {
                fprintf( stderr, "Insanity!\n" );
                ((Ramp*)0)->min = 0;
            }
            index = sortedmax[maxindex];
            newavg = ramps[sortedmax[maxindex]].max;
            ismin = 0;
            if( minindex < r && ramps[sortedmin[minindex]].min < newavg ) {
                newavg = ramps[sortedmin[minindex]].min;
                index = sortedmin[minindex];
                ismin = 1;
            }
            inhoud += ((r - maxindex)-(r-minindex)) * ( newavg * newavg - avg * avg ) * 2;
            solved[index] = newavg;
            if( inhoud > m ) {
                inhoud -= ((r - maxindex)-(r-minindex)) * newavg * newavg * 2;
                solved[index] = sqrt((((float)(m - inhoud)) / ((r - maxindex)-(r-minindex))) / 2);
                inhoud = m;
            }
            if( ismin )
                minindex++;
            else
                maxindex++;
            avg = newavg;
        } while( inhoud < m );
    }
    currmin = solved[0];
    currmax = solved[0];
    for( i = 1; i < r; i++ ) {
        if( currmin > solved[i] )
            currmin = solved[i];
        if( currmax < solved[i] )
            currmax = solved[i];
    }
    float minDiff = currmax - currmin;

    /**
     * Note: the order of the algorithm? I need to sort...
     */
    if( fabs( ( maxDiff - floor( maxDiff ) ) - 0.5 ) < 0.001 )
        fprintf( stderr, "WARNING! CLOSE CALL ON FLOAT!\n" );
    if( fabs( ( minDiff - floor( minDiff ) ) - 0.5 ) < 0.001 )
        fprintf( stderr, "WARNING! CLOSE CALL ON FLOAT!\n" );

    printf( "%.2f %.2f\n", minDiff, maxDiff );
}
