【分析】把每行和每列看成一个点,然后先建一个源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.