POJ 1273 Drainage Ditches 最大流 dinic

题目大意:给出很多个网络,求其最大流

输入:第一行N,M(0<=N<=200,2<=M<=200)

           接下来的N行给出每一条边的起点、终点、流的上限

           M为点数

输出:最大流的数值

很裸的一道最大流,不会的自己百度一下学习(会的话真的没有什么好说的,所以注释偏少)

代码:

const
  maxn=1000;
  maxm=100000;
  maxw=2000000000;
type
  gtype=record
    x,y,f,c,next,op:longint;
  end;
var
  g:array[1..maxm*2] of gtype;
  first,first1:array[1..maxn] of longint;
  p,level,prt:array[1..maxn] of longint;
  visited:array[1..maxn] of boolean;
  n,m,tot,vs,vt,maxflow,temp,i,a,b,c:longint;
  function min(a,b:longint):longint;
  begin
    if a<b then exit(a) else exit(b);
  end;
  procedure add(a,b,c:longint);
  begin
    inc(tot);
    g[tot].x:=a;
    g[tot].y:=b;
    g[tot].c:=c;
    g[tot].next:=first[a];
    first[a]:=tot;
    g[tot].op:=tot+1;
    inc(tot);
    g[tot].x:=b;
    g[tot].y:=a;
    g[tot].c:=0;
    g[tot].next:=first[b];
    first[b]:=tot;
    g[tot].op:=tot-1;             //准备反边
  end;
  procedure make_level;
  var
    i,f,r,temp,tp:longint;
  begin
    for i:=1 to n do level[i]:=maxw;
    fillchar(p,sizeof(p),0);
    f:=1;  r:=1;  p[f]:=vs;  level[vs]:=1;
    repeat
      tp:=p[f];
      if tp=vt then exit;
      temp:=first[tp];
      while temp<>-1 do
      begin
        if level[g[temp].y]>level[tp]+1 then
          if (g[temp].f<g[temp].c) or ((g[temp].c=0) and (g[temp].f>0)) then
            begin
              inc(r);
              p[r]:=g[temp].y;
              level[g[temp].y]:=level[tp]+1;
            end;
        temp:=g[temp].next;
      end;
      inc(f);
    until f>r;
  end;
  procedure dfs_maxflow;
  var
    top,mint,i,temp,tp,ti:longint;
  begin
    fillchar(p,sizeof(p),0);
    fillchar(prt,sizeof(prt),0);
    fillchar(visited,sizeof(visited),false);
    first1:=first;
    top:=1;
    p[1]:=vs;
    while top>0 do
    begin
      if p[top]=vt then
      begin
        mint:=maxw;
        for i:=top downto 2 do
          if g[prt[p[i]]].f<g[prt[p[i]]].c
            then mint:=min(mint,g[prt[p[i]]].c-g[prt[p[i]]].f)
          else
            mint:=min(mint,g[prt[p[i]]].f);
        for i:=top downto 2 do
          if g[prt[p[i]]].f<g[prt[p[i]]].c then
          begin
            g[prt[p[i]]].f:=g[prt[p[i]]].f+mint;
            g[g[prt[p[i]]].op].f:=g[g[prt[p[i]]].op].f+mint;
            if g[prt[p[i]]].f=g[prt[p[i]]].c then ti:=i;
          end
          else
            begin
              g[prt[p[i]]].f:=g[prt[p[i]]].f-mint;
              g[g[prt[p[i]]].op].f:=g[g[prt[p[i]]].op].f-mint;
              if g[prt[p[i]]].f=0 then ti:=i;
            end;
        top:=ti-i;
      end
      else
        begin
          temp:=first1[p[top]];
          tp:=p[top];
          while temp<>-1 do
          begin
            if (not visited[g[temp].y]) and (level[g[temp].y]=level[tp]+1) then
              if (g[temp].f<g[temp].c) or ((g[temp].c=0) and (g[temp].f>0)) then
              begin
                first1[p[top]]:=g[temp].next;
                inc(top);
                p[top]:=g[temp].y;
                prt[p[top]]:=temp;
                break;
              end;
            temp:=g[temp].next;
          end;
          if temp=-1 then
          begin
            visited[p[top]]:=true;
            dec(top);
          end;
        end;
    end;
  end;
begin
  while not eof do
  begin
    fillchar(g,sizeof(g),0);
    readln(m,n);
    fillchar(first,sizeof(first),$ff);
    tot:=0;
    for i:=1 to m do
    begin
      readln(a,b,c);
      add(a,b,c);     //建立网络
    end;
    vs:=1;  vt:=n;
    while true do
    begin
      make_level;
      if level[vt]=maxw then break;
      dfs_maxflow;
    end;             //Dinic
    maxflow:=0;
    temp:=first[vs];
    while temp<>-1 do
    begin
      maxflow:=maxflow+g[temp].f;
      temp:=g[temp].next;
    end;
    writeln(maxflow);
  end; 
end.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值