最大流 二分图模型
X 集合为行, Y集合为列, 对每个数来说,bom[i][j]表示最小的,upp表示最大的。
之后连S到X,Y到T, 求从S到Y的可行流
求可行流时。。 添加附加源点ss,tt...
之后建图方式与 http://blog.youkuaiyun.com/hlyfalsy/article/details/38555467 SGU 176 类似。。
//tpl
//ipqhjjybj_tpl.h
//header.h
#include <cstdio>
#include <cstdlib>
#include <map>
#include <set>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <sstream>
#include <math.h>
#define mp(x,y) make_pair(x,y)
#define pii pair<int,int>
#define pLL pair<long long ,long long>
#define pb(x) push_back(x)
#define rep(i,j,k) for(int i = j; i < k;i++)
#define MAX(x,a) x=((x)<(a))?(a):(x)
#define MIN(x,a) x=((x)>(a))?(a):(x)
using namespace std;
const int N = 305;
int n,m,tot;
int s,t;
int sum;
struct node{
int u,v,w,next;
node(){}
node(int _u,int _v,int _w,int _next){
u=_u,v=_v,w=_w,next=_next;
}
}edge[N*N];
int head[N],cur[N],dis[N];
int pre[N],gap[N],aug[N];
const int oo=0x3f3f3f3f;
void addEdge(int u,int v,int w){
edge[tot]=node(u,v,w,head[u]);
head[u]=tot++;
edge[tot]=node(v,u,0,head[v]);
head[v]=tot++;
}
int SAP(int s,int e,int n){
int max_flow=0,v,u=s;
int id,mindis;
aug[s]=oo;
pre[s]=-1;
memset(dis,0,sizeof(dis));
memset(gap,0,sizeof(gap));
gap[0]=n;
for(int i=0;i <= n;i++)
cur[i]=head[i];
while(dis[s]<n){
if(u==e){
max_flow += aug[e];
for(v=pre[e]; v!=-1; v=pre[v]){
int ed=cur[v];
edge[ed].w -= aug[e];
edge[ed^1].w += aug[e];
aug[v]-=aug[e];
if(edge[ed].w==0) u=v;
}
}
bool flag=false;
for(id=cur[u]; id!=-1;id=edge[id].next){
v=edge[id].v;
if(edge[id].w > 0 && dis[u]==dis[v]+1){
flag=true;
pre[v]=u;
cur[u]=id;
aug[v]=min(aug[u],edge[id].w);
u=v;
break;
}
}
if(flag==false){
if(--gap[dis[u]] == 0) break;
int mindis=n;
for(id=head[u]; id!=-1; id=edge[id].next){
v=edge[id].v;
if(edge[id].w>0 && dis[v] < mindis){
mindis = dis[v];
cur[u]=id;
}
}
dis[u] = mindis + 1;
gap[dis[u]]++;
if(u!=s)u=pre[u];
}
}
return max_flow;
}
int r[N],c[N];
int bom[N][N],upp[N][N];
int in[N];
int fs;
void print(){
int row = 1;
int col = 1;
for(int i = 1;i < fs;i+=2){
printf("%d",edge[i].w+bom[row][col]);
if(col == m){
row++;
col = 1;
printf("\n");
}else {
col++;
printf(" ");
}
}
}
int solve(){
int src = s , des = t;
s = des+1, t = s+1;
int max_flow = 0;
rep(i,0,des+1)
if(in[i] > 0)addEdge(s,i,in[i]),max_flow+=in[i];
else if(in[i] < 0) addEdge(i,t,-in[i]);
// printf("max_flow = %d\n",max_flow);
// printf("s=%d t=%d src=%d des=%d \n",s,t,src,des);
int s1 = SAP(s,t,t+1);
addEdge(des,src,oo);
int s2 = SAP(s,t,t+1);
// printf("s1=%d s2=%d\n",s1,s2);
if(s1 + s2 == max_flow) return 1;
else return -1;
}
int main(){
int cas;
int hang_flag = true;
scanf("%d",&cas);
while(cas--){
if(hang_flag)hang_flag = false;
else printf("\n");
scanf("%d %d",&n,&m);
memset(head,-1,sizeof(head));
memset(in,0,sizeof(in));
tot = s = sum =0;
rep(i,1,n+1) scanf("%d",r+i);
rep(i,1,m+1) scanf("%d",c+i);
memset(bom,0,sizeof(bom));
rep(i,1,n+1)
rep(j,1,m+1)
upp[i][j] = oo;
int q;
scanf("%d",&q);
char op[10];
bool flag = true;
while(q--){
int u,v,w;
scanf("%d %d %s %d",&u,&v,op,&w);
int tu1 = u ,tu2 = u , tv1 = v,tv2 = v;
if(u == 0) tu1 = 1,tu2 = n;
if(v == 0) tv1 = 1,tv2 = m;
rep(i,tu1,tu2+1)
rep(j,tv1,tv2+1){
if(op[0] == '<') if(bom[i][j]>=w)flag=false; else MIN(upp[i][j],w-1);
else if(op[0] == '>') if(upp[i][j]<=w)flag=false; else MAX(bom[i][j],w+1);
else if(bom[i][j]>w||upp[i][j]<w)flag = false; else upp[i][j] = bom[i][j] = w;
}
}
if(flag){
t = n+m+1;
rep(i,1,n+1)
rep(j,1,m+1){
addEdge(i,n+j,upp[i][j] - bom[i][j]);
in[j+n] += bom[i][j];
in[i] -= bom[i][j];
if(upp[i][j] < bom[i][j])
flag = false;
}
fs = tot;
rep(i,1,n+1)
addEdge(s,i,0),in[i]+=r[i],in[s]-=r[i];
rep(i,1,m+1)
addEdge(i+n,t,0),in[i+n]-=c[i],in[t]+=c[i];
}
if(flag && solve() >= 0){
print();
}else{
puts("IMPOSSIBLE");
}
}
return 0;
}