poj2135Farm Tour——最小费用最大流

题目要求从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.


你可能感兴趣的:(网络流,费用流)