POJ2031 & ZOJ1718[Building a Space Station]
MST,不过这个题用Prim可能会快点,表示我写的Kruskal。
两点之间的距离如果比两点半径和小那么建图时把两点距离置为0,这样就保证了重叠和相交的情况。
Var a,b,f:array[1..11000]of longint; e,x,y,z,r:array[1..10000]of extended; n,ans,m:longint; sum:extended; Function cf(x:extended):extended; begin exit(x*x); end; Procedure addgraph(x,y:longint;z:extended); begin inc(m); a[m]:=x; b[m]:=y; e[m]:=z; end; Procedure init; var i,j:longint; dis:extended; begin readln(n); if n=0 then halt; m:=0; for i:=1 to n do readln(x[i],y[i],z[i],r[i]); fillchar(f,sizeof(f),0); for i:=1 to n do for j:=1 to n do if i<>j then begin dis:=sqrt(cf(x[i]-x[j])+cf(y[i]-y[j])+cf(z[i]-z[j])); if dis<=r[i]+r[j] then dis:=0 else dis:=dis-r[i]-r[j]; addgraph(i,j,dis); end; end; Procedure qsort(l,r:longint); var i,j,y:longint; x,z:extended; begin i:=l;j:=r;x:=e[(l+r)shr 1]; Repeat while e[i]<x do inc(i); while e[j]>x do dec(j); if i<=j then begin y:=a[i];a[i]:=a[j];a[j]:=y; y:=b[i];b[i]:=b[j];b[j]:=y; z:=e[i];e[i]:=e[j];e[j]:=z; inc(i);dec(j); end; Until i>j; if i<r then qsort(i,r); if l<j then qsort(l,j); end; Function find(x:longint):longint; var k:longint; begin k:=x; while f[k]<>0 do k:=f[k]; find:=k; end; Procedure kruskal; var i,j,p,q:longint; begin qsort(1,m); sum:=0; ans:=0; for i:=1 to m do begin p:=find(a[i]); q:=find(b[i]); if p<>q then begin f[q]:=p; sum:=sum+e[i]; inc(ans); end; if ans>=n-1 then break; end; writeln(sum:0:3); end; Begin n:=1; while n<>0 do begin init; kruskal; end; End.