type node=record x,y:longint; end;
const maxn=;
var k,q,qq:longint;
sum:double;
f,g:array[..maxn] of node;
m,i,j,a,b:longint;
stack:array[..maxn] of longint;
nm:longint;
function dis(a,b:node):double;
begin
exit(sqrt(sqr(a.x-b.x)+sqr(a.y-b.y)));
end;
procedure swap(var a,b:node); inline;
var c:node;
begin
c:=a; a:=b; b:=c;
end;
function dig(a,b:node):longint; inline;
begin
exit(a.x*b.y-a.y*b.x);
end;
function mk(a,b:node):node; inline;
begin
mk.x:=b.x-a.x;
mk.y:=b.y-a.y;
end;
function cmp(a,b:node):boolean; inline;
var p1,p2:node;
begin
p1:=mk(f[],a);
p2:=mk(f[],b);
if dig(P1,P2)< then exit(true);
if dig(P1,P2)= then
if dis(f[],a)>dis(f[],b) then
exit(true);
exit(false);
end;
procedure sort(l,r:longint);
var i,j:longint;
x:node;
begin
i:=l; j:=r; x:=f[(l+r) div ];
while i<=j do
begin
while cmp(f[i],x) do inc(i);
while cmp(x,f[j]) do dec(j);
if i<=j then
begin
swap(f[i],f[j]);
inc(i); dec(j);
end;
end;
if l<j then sort(l,j);
if i<r then sort(i,r);
end;
begin
readln(q);
for qq:= to q do
begin
readln(m);
for i:= to m do readln(f[i].x,f[i].y);
if m= then begin writeln('0.0'); continue; end;
j:=;
for i:= to m do
if (f[i].y<f[j].y) or (f[i].y=f[j].y) and (f[i].x<f[j].x) then
j:=i;
swap(f[],f[j]);
sort(,m);
k:=;
g[]:=f[]; g[]:=f[];
for i:= to m do
if dig(mk(f[],f[i]),mk(f[],f[i-]))<> then
begin
inc(k);
g[k]:=f[i];
end;
nm:=;
stack[]:=; stack[]:=; stack[]:=;
for i:= to k do
begin
a:=stack[nm-];
b:=stack[nm];
while dig(mk(g[a],g[b]),mk(g[a],g[i]))> do
begin
dec(nm);
a:=stack[nm-];
b:=stack[nm];
end;
inc(nm);
stack[nm]:=i;
end;
sum:=;
while nm>= do
begin
a:=stack[nm];
b:=stack[nm-];
sum:=sum+abs(dig(mk(g[],g[b]),mk(g[],g[a])))/;
dec(nm);
end;
writeln(sum::);
end;
end.
05-02 00:34