题目要求从1到n走一遍再从n到1走一遍而且有重边,相当于从1到n走两边
所以加一个源点0<-->1,费用为0,流量为2
加一个汇点n+1<-->n,费用为0,流量为2
中间的边流量为1(只走一遍),费用为c
然后一遍0->n+1的费用流
要注意是无向图,所以一个输入有4条边
a->b ,c,1
b->a ,-c,0
b->a ,c,1
a->b ,c,0
type point=record a,b,c,f,o,p:longint; //o是反边编号 end; var edge:array[1..40010]of point; n,i,m,a,b1,c,l,cost,top,tail,p,j,min,ttf,ff:longint; head,d,pre,re:array[0..10010]of longint; f:array[0..10010]of boolean; b:array[1..100000]of longint; procedure add(u,v,c,f:longint);//添加边用过程 begin l:=l+1; edge[l].a:=u; edge[l].b:=v; edge[l].c:=c; edge[l].f:=f; edge[l].o:=l+1; edge[l].p:=head[u]; head[u]:=l; l:=l+1; edge[l].a:=v; edge[l].b:=u; edge[l].c:=-c; edge[l].f:=0; edge[l].o:=l-1; edge[l].p:=head[v]; head[v]:=l; end; begin read(n,m); for i:=0 to n+1 do head[i]:=-1; for i:=1 to m do begin read(a,b1,c); add(a,b1,c,1); add(b1,a,c,1); //无向图 end; add(0,1,0,2); add(n,n+1,0,2); cost:=0;ttf:=0; while true do//!! begin top:=1;tail:=1; fillchar(b,sizeof(b),0); b[top]:=0; for i:=0 to n+1 do d[i]:=maxlongint; d[0]:=0; fillchar(f,sizeof(f),true); f[0]:=false; fillchar(pre,sizeof(pre),0); pre[0]:=-1; fillchar(re,sizeof(re),0);//记录i与前驱的边的编号 repeat//SPFA p:=head[b[top]]; while p<>-1 do begin j:=edge[p].b; if (d[j]>d[b[top]]+edge[p].c)and(edge[p].f>0) then begin d[j]:=d[b[top]]+edge[p].c; pre[j]:=b[top];//!不要写错b[top] re[j]:=p; if f[j] then begin f[j]:=false; tail:=tail+1; b[tail]:=j; end; end; p:=edge[p].p; end; f[b[top]]:=true; top:=top+1; until top>tail; if d[n+1]=maxlongint then break; //如果找不到可扩充的流,就结束 min:=maxlongint; i:=n+1; //这个一定要写 while pre[i]<>-1 do begin if min>edge[re[i]].f then min:=edge[re[i]].f; i:=pre[i]; //这个一定要写 end; i:=n+1; while pre[i]<>-1 do begin edge[re[i]].f:=edge[re[i]].f-min; edge[edge[re[i]].o].f:=edge[edge[re[i]].o].f+min; cost:=cost+edge[re[i]].c*min; i:=pre[i]; end; //ttf:=ttf+min; end; //writeln(ttf); writeln(cost); readln;readln; end.