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.
原文地址:https://www.cnblogs.com/stmq/p/2571146.html