• poj1087 网络流


    这是我做的比较满意的一道题,先设一个源点S和一个汇点T,把S指向房间里原有的插座,容量为该插座类型的数量,把设备(插头)指向T,再把,容量为该种类型插头的数量,再把适配器的插头指向插座,容量为无穷大,这就构成了一个网络流的模型,最大流则是可以使用设备的最大数量,用设备总数减去即可

    program poj1087;
    var
      flag:boolean;
      n,len,i,j,i1,j1,max,min,aug:integer;
      a:array[0..402] of string;
      g:array[0..402,0..402] of integer;
      fir,now,t,num,liu:array[0..402] of integer;
    procedure init;
    var
      m,i,j,k,l,p:integer;
      s,s1,s2:string;
    begin
      readln(m);
      len:=2;
      readln(a[len]);
      g[1,len]:=1;
      for i:=2 to m do
      begin
        readln(s);
        j:=2;
        while (j<=len) and (a[j]<>s) do inc(j);
        if j<=len then inc(g[1,j])
          else
          begin
            inc(len);
            a[len]:=s;
            g[1,len]:=1;
          end;
      end;
      readln(m);
      n:=m;
      for i:=1 to m do
      begin
        readln(s);
        p:=pos(' ',s);
        s1:=copy(s,p+1,length(s)-p);
        j:=2;
        while (j<=len) and (a[j]<>s1) do inc(j);
        if j<=len then inc(g[j,0])
          else
          begin
            inc(len);
            a[len]:=s1;
            g[len,0]:=1;
          end;
      end;
      readln(m);
      for i:=1 to m do
      begin
        readln(s);
        p:=pos(' ',s);
        s1:=copy(s,1,p-1);
        s2:=copy(s,p+1,length(s)-p);
        j:=0;
        k:=0;
        for l:=2 to len do
          if a[l]=s1 then j:=l
            else if a[l]=s2 then k:=l;
        if j=0 then
        begin
          inc(len);
          a[len]:=s1;
          j:=len;
        end;
        if k=0 then
        begin
          inc(len);
          a[len]:=s2;
          k:=len;
        end;
        g[k,j]:=maxint;
      end;
      for i:=1 to len do
        g[i,len+1]:=g[i,0];
      inc(len);
    end;
    begin
      fillchar(g,sizeof(g),0);
      fillchar(fir,sizeof(fir),0);
      fillchar(now,sizeof(now),0);
      fillchar(t,sizeof(t),0);
      fillchar(num,sizeof(num),0);
      fillchar(liu,sizeof(liu),0);
      init;
      for i:=1 to len do
        now[i]:=1;
      t[0]:=len;
      i:=1;
      aug:=maxint;
      max:=0;
      while num[i]<len do
      begin
        flag:=false;
        liu[i]:=aug;
        for j:=now[i] to len do
          if (g[i,j]>0) and (num[j]+1=num[i]) then
          begin
            flag:=true;
            if g[i,j]<aug then aug:=g[i,j];
            fir[j]:=i;
            now[i]:=j;
            i:=j;
            if i=len then
            begin
              inc(max,aug);
              while i<>1 do
              begin
                i1:=i;
                i:=fir[i];
                dec(g[i,i1],aug);
                inc(g[i1,i],aug);
              end;
              aug:=maxint;
            end;
            break;
          end;
        if flag then continue;
        min:=len-1;
        for j:=1 to len do
          if (g[i,j]>0) and (num[j]<min) then
          begin
            j1:=j;
            min:=num[j];
          end;
        now[i]:=j1;
        dec(t[num[i]]);
        if t[num[i]]=0 then break;
        num[i]:=min+1;
        inc(t[num[i]]);
        if i<>1 then
        begin
          i:=fir[i];
          aug:=liu[i];
        end;
      end;
      writeln(n-max);
    end.
    
  • 相关阅读:
    问题 E: C#判断回文字符串
    hdu 1130 How Many Trees? 【卡特兰数】
    The writing on the wall
    字典树的应用
    完全背包
    多重背包
    hdu 2191 【背包问题】
    最长上升子序列 and 最长公共子序列 问题模板
    hdu 4704 Sum 【费马小定理】
    费马小定理
  • 原文地址:https://www.cnblogs.com/stmq/p/2571146.html
Copyright © 2020-2023  润新知