解题报告 poj 1087

题意可以百度。

话说,这是一个很 YD 的最大流模型题。不过似乎可用 floyd+匈牙利 做。

最大流模板就不说了,主要说一下构图。(也就是这个题 YD 的地方)

大致方向是这样的:虚拟源点和汇点,所有插座与汇点连边,方向指向汇点,流量为 1 。所有用电器和源点连边,指向用电器,流量为 1 。然后可以转换插头的再连边,流量为 +∞ (因为他给出的是转换器的种类,个数不限)。

但是,YD 的地方是这里:有数据是用电器的插头的型号与插座都不一样,也就是图不连通。还有数据是有转换器的两个节点既不是用电器也不是插座,也就是需要为转换器另开节点。这样一来,总的节点数就是:m(用电器)+n(插座)+tot(为那种特殊的转换器新申请的节点)+2(源点和汇点)。

还有一个更 YD 的,就是,当最大流>用电器,就是说将这些用电器全插上之后插座还有富余,这时要输出 0 而不是负数。

代码(SueMiller):

program ACRush;
var n,m,mm:longint;
    i,j,k,ii,jj,kk,ss,tt,tot:longint;
    a,b,c:array[0..510]of string;
    t:array[0..510,0..510]of longint;
    q:array[0..3010]of longint;
    num:array[0..510]of longint;
    s,s1,s2:string;
    ans:longint;

function min(a,b:longint):longint;
begin
  if a<b then exit(a) else exit(b);
end;

function bfs:boolean;
var head,tail:longint;
    i:longint;
begin
  fillchar(num,sizeof(num),0);
  head:=0;
  tail:=1;
  q[1]:=ss;
  num[ss]:=1;
  while head<tail do
    begin
      inc(head);
      for i:=0 to n+m+tot+1 do
        if t[q[head],i]>0 then
          if num[i]=0 then
            begin
              num[i]:=num[q[head]]+1;
              inc(tail);
              q[tail]:=i;
            end;
    end;
  if num[tt]=0 then exit(false) else exit(true);
end;

function dfs(now,flow:longint):longint;
var i,temp:longint;
begin
  if now=tt then exit(flow);
  for i:=0 to n+m+tot+1 do
    if t[now,i]>0 then
      if num[i]=num[now]+1 then
        begin
          temp:=dfs(i,min(flow,t[now,i]));
          if temp>0 then
            begin
              dec(t[now,i],temp);
              inc(t[i,now],temp);
              exit(temp);
            end;
        end;
  exit(0);
end;

begin
  readln(n);
  for i:=1 to n do
    readln(a[i]);
  readln(m);

  for i:=1 to m do
    begin
      readln(s);
      s1:=copy(s,pos(' ',s)+1,length(s)-pos(' ',s));
      for j:=1 to n do
        if a[j]=s1 then
          begin
            t[i,j+m]:=maxlongint>>2;
          end;
      b[i]:=s1;
    end;

  readln(mm);
  for i:=1 to mm do
    begin
      readln(s);
      s2:=copy(s,pos(' ',s)+1,length(s)-pos(' ',s));
      s1:=copy(s,1,pos(' ',s)-1);
      ii:=0;jj:=0;
      for j:=1 to n+m+tot do
        begin
          if (j>m) and (j<=m+n) then
            begin
              if a[j-m]=s1 then ii:=j;
              if a[j-m]=s2 then jj:=j;
            end;
          if j<=m then
            begin
              if b[j]=s1 then ii:=j;
              if b[j]=s2 then jj:=j;
            end;
          if j>m+n then
            begin
              if c[j-m-n]=s1 then ii:=j;
              if c[j-m-n]=s2 then jj:=j;
            end;
          if (ii>0) and (jj>0) then t[ii,jj]:=maxlongint>>2;
        end;

      if ii=0 then
        begin
          inc(tot);
          c[tot]:=s1;
        end;
      if jj=0 then
        begin
          inc(tot);
          c[tot]:=s2;
        end;
      if (ii=0) and (jj=0) then
        t[m+n+tot-1,m+n+tot]:=maxlongint>>2;
    end;

  ss:=0;tt:=m+n+tot+1;
  for i:=1 to m do
    t[ss,i]:=1;
  for i:=m+n+1 to m+n+tot do
    t[ss,i]:=1;
  for i:=m+1 to m+n do
    t[i,tt]:=1;

  ans:=0;
  while bfs do
    begin
      kk:=dfs(ss,maxlongint>>2);
      while kk>0 do
        begin
          inc(ans,kk);
          kk:=dfs(ss,maxlongint>>2);
        end;
    end;

  if ans>m then ans:=m;
  writeln(m-ans);
end.

 

 

posted @ 2012-02-16 11:50  木小漾  阅读(207)  评论(0编辑  收藏  举报