unittest
{
	assert( [ "1", "2", "1 5 10", "1 5 11" ].solve == "16" );
	assert( [ "3", "2", "1 5 10", "2 15 5", "3", "2 93 78", "1 71 59", "3 57 96", "19", "19 23 16", "5 90 13", "12 85 70", "19 67 78", "12 16 60", "18 48 28", "5 4 24", "12 97 97", "4 57 87", "19 91 74", "18 100 76", "7 86 46", "9 100 57", "3 76 73", "6 84 93", "1 6 84", "11 75 94", "19 15 3", "12 11 34" ].solve == "25\n221\n1354" );
}



import std.algorithm;
import std.conv;
import std.format;
import std.range;
import std.stdio;
import std.typecons;

void main()
{
	stdin.byLineCopy.solve.writeln;
}

auto solve( Range )( Range input )
if( isInputRange!Range && is( ElementType!Range == string ) )
{
	auto t = input.front.to!( long );
	auto ss = new long[ t ];
	auto lkss = new long[ 2 ][][ t ];
	auto rkss = new long[ 2 ][][ t ];
	foreach( ref s, ref lks, ref rks; lockstep( ss, lkss, rkss ) )
	{
		input.popFront;
		auto n = input.front.to!( long );
		foreach( i; 0L .. n )
		{
			input.popFront;
			auto klr = input.front.split.to!( long[] );
			s += min( klr[ 1 ], klr[ 2 ] );
			if( klr[ 2 ] <= klr[ 1 ] ) lks ~= [ klr[ 1 ] - klr[ 2 ], klr[ 0 ] ];
			else                       rks ~= [ klr[ 2 ] - klr[ 1 ], n - klr[ 0 ] ];
		}
		lks.sort!( ( a, b ) => b < a );
		rks.sort!( ( a, b ) => b < a );
	}
	
	auto anss = new long[ t ];
	foreach( ref ans, s, lks, rks; lockstep( anss, ss, lkss, rkss ) )
	{
		// 並べ替え用の初期値を作成
		ans = s;
		auto zs = new Tuple!( long, long )[ max( lks.length, rks.length ) ];
		foreach( i, ref z; zs )
		{
			z = tuple( 0L, i );
		}
		
		// 左端からk番目以内に置くとプラスになるラクダを並べる
		ans += solve2( zs, lks );
		
		// 右端からn-k番目以内に置くとプラスになるラクダを並べる
		ans += solve2( zs, rks );
	}
	return anss.to!( string[] ).join( "\n" );
}

auto solve2( Tuple!( long, long )[] zs, long[ 2 ][] pks )
{
	auto s = 0L;
	auto st = SegmentTree!( Tuple!( long, long ), ( a, b ) => a[ 0 ] < b[ 0 ] || ( a[ 0 ] == b[ 0 ] && b[ 1 ] < a[ 1 ] ) ? a : b, tuple( long.max, long.min ) )( zs[ 0 .. pks.length ] );
	foreach( pk; pks )
	{
		auto q = st.query( 0, min( pk[ 1 ], pks.length ) );
		if( q[ 0 ] < pk[ 0 ] )
		{
			s += pk[ 0 ] - q[ 0 ];
			st.set( q[ 1 ], tuple( pk[ 0 ], q[ 1 ] ) );
		}
	}
	return s;
}

// セグメント木
struct SegmentTree( T, alias op = ( ( a, b ) => a + b ), T I = T.init )
{
	T[] ts;
	
	this( long n )
	{
		ts = new T[ n << 1 ];
		static if( I != T.init ) ts[] = I;
	}
	
	this( T[] qs )
	{
		ts = new T[ qs.length << 1 ];
		ts[ $ >> 1 .. ( $ >> 1 ) + qs.length ] = qs;
		foreach_reverse( i; 1L .. ts.length.signed >> 1 )
		{
			ts[ i ] = op( ts[ i << 1 ], ts[ i << 1 | 1 ] );
		}
	}
	
	void set( long i, T v )
	{
		i += ts.length.signed >> 1;
		ts[ i ] = v;
		for( i >>= 1; 0 < i; i >>= 1 )
		{
			ts[ i ] = op( ts[ i << 1 ], ts[ i << 1 | 1 ] );
		}
	}
	
	auto get( long i )
	{
		i += ts.length.signed >> 1;
		return ts[ i ];
	}
	
	auto query( long l, long r )
	{
		l += ts.length.signed >> 1;
		r += ts.length.signed >> 1;
		auto x = I;
		auto y = I;
		for( ; l < r; l >>= 1, r >>= 1 )
		{
			if( l & 1 )
			{
				x = op( x, ts[ l ] );
				l++;
			}
			if( r & 1 )
			{
				r--;
				y = op( ts[ r ], y );
			}
		}
		return op( x, y );
	}
	
	auto length()
	{
		return ts.length >> 1;
	}
	
	auto toString()
	{
		return format( "ST(%s)", ts[ $ >> 1 .. $ ] );
	}
}
