用的是我和盾盾研究出来的“距离标号连续最短增广路算法”,实测效果极佳 先贴代码,下次再解释 program syj; const maxn=105; maxm=maxn*(maxn-1)>>1; oo=maxlongint>>1; var e,s,t,n,m,nn,ans,i,j,x:longint; ok:boolean; h,d,b,sl:array[0..maxm+maxn]of longint; next,point,w,c:array[-(maxm*3+maxn)..maxm*3+maxn]of longint; v:array[0..maxm+maxn]of boolean; g:array[1..maxn,1..maxn]of longint; procedure link(x,y,z:longint); begin inc(e); next[e]:=h[x];point[e]:=y;c[e]:=z;w[e]:=1;h[x]:=e; next[-e]:=h[y];point[-e]:=x;c[-e]:=-z;w[-e]:=0;h[y]:=-e; end; procedure dfs(i:longint); var j,k:longint; begin if i=t then begin inc(ans,b[t]-b[s]);ok:=true;exit; end; v[i]:=true; j:=h[i]; while j<>0 do begin k:=point[j]; if (w[j]>0)and(c[j]+b[i]-b[k]<sl[k]) then sl[k]:=c[j]+b[i]-b[k]; if (w[j]>0)and(c[j]+b[i]=b[k])and not v[k] then begin dfs(k); if ok then begin w[j]:=0;w[-j]:=1; ok:=ok and(i<>s); //!! many road improving if ok then exit; end; end; j:=next[j]; end; end; function find:boolean; var i,z:longint; begin z:=oo; for i:=0 to nn do if not v[i]and(sl[i]<z) then z:=sl[i]; if z=oo then exit(false); for i:=0 to nn do if v[i] then dec(b[i],z); find:=true; end; begin assign(input,'jsb.in');reset(input); assign(output,'jsb.out');rewrite(output); readln(n); m:=n; s:=0; for i:=1 to n do for j:=1 to n do begin read(g[i,j]); if i>=j then continue; x:=g[i,j]; if x=1 then inc(d[j]) else if x=0 then inc(d[i]) else begin inc(m); link(m,i,0);link(m,j,0); link(0,m,0); end; end; t:=m+1; nn:=m+1; for i:=1 to n do begin inc(ans,d[i]*d[i]); for j:=d[i]+1 to n-1 do link(i,t,2*j-1); end; while find do begin fillchar(sl,sizeof(sl),127); repeat fillchar(v,sizeof(v),0); ok:=false; dfs(s); until not ok; end; writeln(n*(n-1)*(n-2)div 6+(n*(n-1)div 2-ans)div 2); close(input);close(output); end.