十三、网络流

网络流的最经典应用就是最大流....给定一个图...给出每条边能流过的最大流量...求源点到汇点的最大流量....

   求解网络流的基本思想就是每次寻找增广路(就是源点到汇点的一条可行路)..然后ans+=增广路能流过的流量..更新剩余网络..然后再做增广路...直到做不出增广路..关于网络流入门最难理解的地方就是剩余网络了....为什么在找到一条增广路后...不仅要将每条边的可行流量减去增广路能流过的流量...还要将每条边的反向弧加上增广路能流过的流量.?..原因是在做增广路时可能会阻塞后面的增广路...或者说做增广路本来是有个顺序才能找完最大流的.....但我们是任意找的...为了修正...就每次将流量加在了反向弧上...让后面的流能够进行自我调整...剩余网络的更新(就在原图上更新就可以了)。

注意:

当要控制流量时可拆点,当有多个源点或汇点时可建立超级源点或超级汇点。

可观察数据范围推测是否用网络流。

网络流模板最好背下来。大笑


模板:

type
  node=record
    y,r,next,op:longint;
  end;
var
  g:array [1..400] of node;
  h,level,q:array [1..400] of longint;
  i,j,m,n,ans,a,b,c,vs,vt,tot:longint;


function min(x,y:longint):longint;
begin
  if x<y then
  exit(x);
  exit(y);
end;


function dfs(v,a:longint):longint;
var
  tmp,u,ans,value,flow:longint;
begin
  if (v=vt) or (a=0) then exit(a);
  ans:=0;
  tmp:=h[v];
  while tmp<>-1 do
  begin
    u:=g[tmp].y;
    value:=g[tmp].r;
    if level[v]+1=level[u] then
    begin
      flow:=dfs(u,min(a,value));
      if flow<>0 then
      begin
        g[tmp].r:=g[tmp].r-flow;
        g[g[tmp].op].r:=g[g[tmp].op].r+flow;
        ans:=ans+flow;
        a:=a-flow;
        if a=0 then break;
      end;
    end;
    tmp:=g[tmp].next;
  end;
  exit(ans);
end;


function bfs:boolean;
var
  u,tmp,l,f,v:longint;
begin
  fillchar(level,sizeof(level),0);
  q[1]:=vs;
  level[vs]:=1;
  l:=1;
  f:=1;
  repeat
    v:=q[l];
    tmp:=h[v];
    while tmp<>-1 do
    begin
      u:=g[tmp].y;
      if (g[tmp].r<>0) and (level[u]=0) then
      begin
        level[u]:=level[v]+1;
        inc(f);
        q[f]:=u;
        if u=vt then exit(true);
      end;
      tmp:=g[tmp].next;
    end;
    inc(l);
  until l>f;
  exit(false);
end;


procedure add(a,b,c:longint);
begin
  inc(tot);
  g[tot].y:=b;
  g[tot].r:=c;
  g[tot].next:=h[a];
  h[a]:=tot;
  g[tot].op:=tot+1;
  inc(tot);
  g[tot].y:=a;
  g[tot].r:=0;
  g[tot].next:=h[b];
  h[b]:=tot;
  g[tot].op:=tot-1;
end;


begin
  while not eof do
  begin
    fillchar(g,sizeof(g),0);
    fillchar(h,sizeof(h),$ff);
    fillchar(level,sizeof(level),0);
    fillchar(q,sizeof(q),0);
    readln(n,m);
    tot:=0;
    ans:=0;
    vs:=1;
    vt:=m;
    for i:=1 to n do
    begin
      readln(a,b,c);
      add(a,b,c);
    end;
    while bfs do
    ans:=ans+dfs(vs,maxlongint);
    writeln(ans);
  end;
end.


有几道网络流题目:

poj1273

poj1274

poj1149

poj3281

poj3498




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值