容量有上下界的可行流

来源:互联网 发布:sqlserver 2008 个人版 编辑:程序博客网 时间:2024/05/17 01:43

【分析】把每行和每列看成一个点,然后先建一个源S和汇T,行就与S连,边的上下界均为要求的和,列就
与T连,上下界也是和,根据限制条件,调整行与列之间的关系。然后图就建好一半了。然后就是
求这个有上下界的网络的可行流
amber的《图论总结》里也写到怎么求
【复杂度】O(Maxflow)
【小结】 这题模型有点难想,但是建图十分麻烦。然后我的程序一直不能AC,我很郁闷,不知道为什么,
先贴一下,如果有人知道的话联系我

type ok=record     x,y,nt:longint;     end;var tc,n,m,st,en,ptot,tot,sum:longint;    e:Array[1..100000]of ok;    head,cur,stack,d,inflow,outflow:array[0..500]of longint;    map,minm,maxm:array[0..500,0..500]of longint;    flag:boolean;procedure add(a,b,c:longint);begin  inc(tot);  e[tot].x:=a;e[tot].y:=b;  e[tot].nt:=head[a];head[a]:=tot;  map[a,b]:=c;  inc(tot);  e[tot].x:=b;e[tot].y:=a;  e[tot].nt:=head[b];head[b]:=tot;end;procedure change(x,y,z:longint;ch:char);begin  if ch='=' then begin minm[x,y]:=z;maxm[x,y]:=z;end;  if ch='>' then begin if z>=minm[x,y] then minm[x,y]:=z+1;end;  if ch='<' then begin if z<=maxm[x,y] then maxm[x,y]:=z-1;end;  if minm[x,y]>maxm[x,y] then flag:=true;end;procedure fill;var i,j:longint;begin  fillchar(outflow,sizeof(outflow),0);  fillchar(inflow,sizeof(inflow),0);  fillchar(head,sizeof(head),0);  fillchar(map,sizeof(map),0);  for i:=0 to 500 do    for j:=0 to 500 do      begin      minm[i,j]:=0;maxm[i,j]:=1001;      end;  st:=0;en:=n+m+1;tot:=0;flag:=false;sum:=0;end;function bfs:boolean;var i,t,k,k1,now:longint;begin  for i:=0 to en do d[i]:=-1;  stack[1]:=st;d[st]:=0;  k:=0;k1:=1;  while k<k1 do    begin    inc(k);now:=stack[k];    t:=head[now];cur[now]:=t;    while t<>0 do      begin      if (map[e[t].x,e[t].y]>0)and(d[e[t].y]=-1) then        begin        inc(k1);stack[k1]:=e[t].y;        d[e[t].y]:=d[now]+1;        end;      t:=e[t].nt;      end;    end;  if d[en]=-1 then exit(false) else exit(true);end;function dinic(now,tot:longint):longint;var s,temp,flow:longint;begin  if now=en then exit(tot);  s:=0;  while cur[now]<>0 do    begin    if (map[now,e[cur[now]].y]>0)and(d[e[cur[now]].y]=d[now]+1) then      begin      temp:=tot;if map[now,e[cur[now]].y]<temp then temp:=map[now,e[cur[now]].y];      flow:=dinic(e[cur[now]].y,temp);      inc(s,flow);      dec(tot,flow);      dec(map[now,e[cur[now]].y],flow);      inc(map[e[cur[now]].y,now],flow);      if tot=0 then break;      end;    cur[now]:=e[cur[now]].nt;    end;  exit(s);end;procedure print;var i,j:longint;begin  for i:=1 to n do    begin    for j:=1 to m do      begin      write(map[j+n,i]+minm[i,j+n]);      if j<m then write(' ');      end;    writeln;    end;end;procedure work;var ans,i,j:longint;begin  ans:=0;  while bfs do ans:=ans+dinic(st,maxlongint);  {writeln(ans);  for i:=0 to n+m+3 do      begin      for j:=0 to m+n+3 do write(map[i,j],' ');      writeln;      end;writeln;}  if ans<>sum div 2 then begin writeln('IMPOSSIBLE');exit;end;  st:=0;en:=n+m+1;  for i:=ptot+1 to tot do    begin    map[e[i].x,e[i].y]:=0;//head[e[i].x]:=e[i].nt;    end;  ans:=0;  while bfs do ans:=ans+dinic(st,maxlongint);  print;end;procedure main;var lim,tt,i,j,k,x,y,z:longint;    ch,tch:char;begin  readln(tc);  for tt:=1 to tc do    begin    if tt>1 then writeln;    //writeln(tc-tt+1);    readln;readln(n,m);    //fillchar    fill;    for i:=1 to n do begin read(x);minm[st,i]:=x;;maxm[st,i]:=x;end;readln;    for i:=1 to m do begin read(x);minm[i+n,en]:=x;;maxm[i+n,en]:=x;end;readln;    readln(lim);    for i:=1 to lim do      begin      read(x,y,tch,ch,tch,z);      if (x=0)and(y=0) then        begin        for j:=1 to n do          for k:=1 to m do            change(j,k+n,z,ch);        continue;        end;      if x=0 then for j:=1 to n do change(j,y+n,z,ch);      if y=0 then for j:=1 to m do change(x,j+n,z,ch);      if (x<>0)and(y<>0) then change(x,y+n,z,ch);      end;    if flag then begin writeln('IMPOSSIBLE');continue;end;    //set up graph    for i:=1 to n do      begin      inc(outflow[st],minm[st,i]);inc(inflow[i],minm[st,i]);      add(st,i,maxm[st,i]-minm[st,i]);//add(i,st,0,-1);      end;    for i:=1 to m do      begin      inc(outflow[i+n],minm[i+n,en]);inc(inflow[en],minm[i+n,en]);      add(i+n,en,maxm[i+n,en]-minm[i+n,en]);//add(en,i+n,0,-1);      end;    for i:=1 to n do      for j:=1 to m do        begin        inc(outflow[i],minm[i,j+n]);inc(inflow[j+n],minm[i,j+n]);        add(i,j+n,maxm[i,j+n]-minm[i,j+n]);//add(j+n,i,0,-1);        end;    st:=n+m+2;en:=n+m+3;ptot:=tot;    for i:=0 to n+m+1 do      begin      inc(sum,inflow[i]);inc(sum,outflow[i]);      add(st,i,inflow[i]);//add(i,st,0,-1);      add(i,en,outflow[i]);//add(en,i,0,-1);      end;    add(n+m+1,0,99999999);//add(0,n+m+1,0,-1);    {writeln(sum);    for i:=0 to n+m+1 do      begin      for j:=0 to m+n+1 do write(minm[i,j],' ');      writeln;      end;writeln;        for i:=0 to n+m+1 do      begin      for j:=0 to m+n+1 do write(maxm[i,j],' ');      writeln;      end;writeln;    for i:=0 to n+m+3 do      begin      for j:=0 to m+n+3 do write(map[i,j],' ');      writeln;      end;}    work;    end;end;begin  assign(input,'1.in');  reset(input);  assign(output,'1.out');  rewrite(output);  main;  close(input);  close(output);end.
0 0