bzoj 1797: [Ahoi2009]Mincut 最小割 (网络流)

太神了直接看了hzwer的题解,有个新认识,一条路径上满流的一定是这条路径上所有边的最小值。

 

 

type
  arr=record
    toward,next,cap,from:longint;
  end;
const
  maxm=200000;
  maxn=10000;
var
  edge:array[0..maxm]of arr;
  first,cur,d,p,gap:array[0..maxn]of longint;
  chose1,chose2:array[0..maxn]of boolean;
  n,m,s,t,tot,esum:longint;
 
function min(x,y:longint):longint;
begin
  if x<y then exit(x);
  exit(y);
end;
 
procedure add(j,k,l:longint);
begin
  inc(esum);
  edge[esum].from:=j;
  edge[esum].toward:=k;
  edge[esum].next:=first[j];
  first[j]:=esum;
  edge[esum].cap:=l;
end;
 
procedure addedge(j,k,l:longint);
begin
  add(j,k,l);
  add(k,j,0);
end;
 
function sap(x,flow:longint):longint;
var
  now,more,i,too:longint;
begin
  if x=t then exit(flow);
  now:=0;
  i:=cur[x];
  while i>=0 do begin
    too:=edge[i].toward;
    if (d[x]=d[too]+1) and (edge[i].cap>0) then begin
      more:=sap(too,min(flow-now,edge[i].cap));
      dec(edge[i].cap,more);
      inc(edge[i xor 1].cap,more);
      inc(now,more);
      cur[x]:=i;
      if now=flow then exit(flow);
    end;
    i:=edge[i].next;
  end;
  dec(gap[d[x]]);
  if gap[d[x]]=0 then d[s]:=n;
  inc(d[x]);
  inc(gap[d[x]]);
  cur[x]:=first[x];
  exit(now);
end;
 
procedure maxflow;
var
  i:longint;
begin
  fillchar(d,sizeof(d),0);
  fillchar(gap,sizeof(gap),0);
  gap[0]:=n;
  for i:=1 to n do cur[i]:=first[i];
  while d[s]<n do sap(s,maxlongint);
end;
 
procedure into;
var
  i,j,k,l:longint;
begin
  esum:=-1;
  fillchar(first,sizeof(first),255);
  readln(n,m,s,t);
  for i:=1 to m do begin
    readln(j,k,l);
    addedge(j,k,l);
  end;
end;
 
procedure work;
var
  head,tail,x,y,i,j,too:longint;
begin
  maxflow;
 { for i:=0 to m<<1 do
    writeln(edge[i].from,' ',edge[i].toward,' ',edge[i].next,' ',edge[i].cap); }
  head:=1;
  tail:=1;
  p[1]:=s;
  fillchar(chose1,sizeof(chose1),false);
  chose1[s]:=true;
  while head<=tail do begin
    x:=p[head];
    i:=first[x];
    while i>=0 do begin
      too:=edge[i].toward;
      if (edge[i].cap>0) and (not chose1[too]) then begin
        inc(tail);
        p[tail]:=too;
        chose1[too]:=true;
      end;
      i:=edge[i].next;
    end;
    inc(head);
  end;
  //for i:=1 to n do writeln(i,' ',chose1[i]);
  head:=1;
  tail:=1;
  p[1]:=t;
  fillchar(chose2,sizeof(chose2),false);
  chose2[t]:=true;
  while head<=tail do begin
    x:=p[head];
    i:=first[x];
    while i>=0 do begin
      too:=edge[i].toward;
      if (edge[i xor 1].cap>0) and (not chose2[too]) then begin
        inc(tail);
        p[tail]:=too;
        chose2[too]:=true;
      end;
      i:=edge[i].next;
    end;
    inc(head);
  end;
  //for i:=1 to n do writeln(i,' ',chose2[i]);
  for i:=1 to m do begin
    j:=(i-1)<<1;
    if edge[j].cap>0 then begin
      writeln(0,' ',0);
      continue;
    end;
    x:=edge[j].from;
    y:=edge[j].toward;
    if not ( (chose1[x] and chose1[y]) or (chose2[x] and chose2[y]) )then write(1) else write(0);
    write(' ');
    if (chose1[x] and chose2[y]) or (chose1[y] and chose2[x])then writeln(1) else writeln(0);
  end;
  readln;
end;
 
begin
  into;
  work;
end.
View Code

 

posted @ 2015-03-22 22:03  Macaulish  阅读(195)  评论(0编辑  收藏  举报