var fa:array[1..30000] of longint;//老大... a,b,c:array[1..30000] of longint;//b(起点)和c(终点)的长度为a i,j,n,m,k,l,ans:longint;//ans是答案
proceduresort(l,r:longint);var i,j,s,t:longint; begin i:=l; j:=r; s:=a[(l+r) div2]; repeatwhile a[i]<s do i:=i+1; while a[j]>s do j:=j-1; if i<=j thenbegin t:=a[i]; a[i]:=a[j]; a[j]:=t; t:=b[i]; b[i]:=b[j]; b[j]:=t; t:=c[i]; c[i]:=c[j]; c[j]:=t; inc(i); dec(j); end; until i>=j; if i<r then sort(i,r); if j>l then sort(l,j); end; //pascal手打排序,不必在意。注意,路径用来排序时起点和终点也要换
procedurestart;//输入和排序,本人使用一维数组 var t,p:longint; begin p:=0; read(n); for i:=1to n do fa[i]:=i; for i:=1to n do for j:=1to n do begin inc(p); b[p]:=i; c[p]:=j; read(a[p]); if i=j then a[p]:=maxlongint; end;
sort(1,n*n); end;
functionget(x:longint):longint;//找根... begin if fa[x]=x then exit(x) else begin get:=get(fa[x]);//递归father fa[x]:=get;//路径压缩 end; end;
proceduremin_way(x:longint); var i,j:longint; begin i:=b[x];//b点和c点要连边 j:=c[x]; if (i<>j) then//不是同一个点 begin fa[i]:=get(i);//找老大 fa[j]:=get(j);//找老大 if (fa[i]<>fa[j]) then//不是同一个组合(不是同一个连通分支) begin inc(ans,a[x]);//加上本路径 fa[get(j)]:=fa[i];//合并 end; end; if x=n*n then//合并完成 exit; min_way(x+1);//下一个需要合并的边 end;