明显拆点费用流;
type arr=record toward,next,cap,cost:longint; end; const mm=1<<30; maxn=1000; maxm=300000; var edge:array[0..maxm]of arr; first,slack,d:array[0..maxn]of longint; chose:array[0..maxn]of boolean; s,t,n,m,tot,esum,maxflow,maxcost:longint; function min(x,y:longint):longint; begin if x<y then exit(x); exit(y); end; procedure add(i,j,k,l:longint); begin inc(esum); edge[esum].toward:=j; edge[esum].next:=first[i]; first[i]:=esum; edge[esum].cap:=k; edge[esum].cost:=l; end; procedure addedge(i,j,k,l:longint); begin add(i,j,k,l); add(j,i,0,-l); end; function aug(x,flow:longint):longint; var now,more,i,too,value:longint; begin if x=t then begin inc(maxflow,flow); inc(maxcost,flow*d[s]); exit(flow); end; now:=0; chose[x]:=true; i:=first[x]; while i>=0 do begin too:=edge[i].toward; value:=edge[i].cost; if (edge[i].cap>0) and (not chose[too]) then if d[x]=d[too]+value then begin more:=aug(too,min(edge[i].cap,flow-now)); dec(edge[i].cap,more); inc(edge[i xor 1].cap,more); inc(now,more); if flow=now then exit(flow); end else slack[too]:=min(slack[too],d[too]+value-d[x]); i:=edge[i].next; end; exit(now); end; function rel:boolean; var i,spent:longint; begin spent:=maxlongint; for i:=1 to tot do if not chose[i] then spent:=min(spent,slack[i]); if spent>=mm then exit(false); for i:=1 to tot do if chose[i] then inc(d[i],spent); exit(true); end; procedure into; var i,j,k,l:longint; begin esum:=-1; fillchar(first,sizeof(first),255); readln(n,m); s:=1; t:=n<<1; tot:=t; for i:=2 to n-1 do addedge(i<<1-1,i<<1,1,0); addedge(1,2,maxlongint,0); addedge(n<<1-1,n<<1,maxlongint,0); for i:=1 to m do begin readln(j,k,l); addedge(j<<1,k<<1-1,1,l); end; fillchar(d,sizeof(d),0); end; begin into; maxcost:=0; maxflow:=0; repeat fillchar(slack,sizeof(slack),$7f); repeat fillchar(chose,sizeof(chose),false); until aug(s,maxlongint)<=0; until not rel; writeln(maxflow,' ',maxcost); end.