给定矩阵的每行每列的和,和一些大于小于等于的限制。然后需要求出一组可行解。
上下界网络流。
大概的思想就是计算出每一个点他需要强行流入或者流出的量,然后建出超级源点和汇点,然后删除下界,就可以判断是否可行。
然后把新的上界作为限制,在原图中跑一边。
然后就是必须的+原图中的进行计算。
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (int i=j;i<=k;++i)
int up[205][205],down[205][205],tt,n,m,row[205];
#define inf 0x3f3f3f3f
#define maxn 50005
int ttt,clu[205],S=maxn-4,T=maxn-3,SS=maxn-2,TT=maxn-1;
int fr[maxn],h[maxn],to[maxn],ne[maxn],fl[maxn],en=0,ans,a[205][205];
int du[maxn],id[205][205],tot,Sum,s,t,ban[maxn],SSum,SSSum; void add(int a,int b,int c)
{
fr[en]=a;to[en]=b;ne[en]=h[a];fl[en]=c;h[a]=en++;
fr[en]=b;to[en]=a;ne[en]=h[b];fl[en]=0;h[b]=en++;
} int dis[maxn];
queue<int>q; bool tell()
{
memset(dis,-1,sizeof dis); dis[s]=0; q.push(s);
while (!q.empty())
{
int x=q.front();q.pop();
for (int i=h[x];i>=0;i=ne[i])
if (dis[to[i]]==-1&&fl[i]>0&&!ban[i])
dis[to[i]]=dis[x]+1,q.push(to[i]);
}
return dis[t]!=-1;
} int zeng(int k,int now)
{
int ret=0;
if (k==t) return now;
for (int i=h[k];i>=0&&now>ret;i=ne[i])
if (dis[to[i]]==dis[k]+1&&fl[i]&&!ban[i]){
int tmp=zeng(to[i],min(fl[i],now-ret));
fl[i]-=tmp; fl[i^1]+=tmp; ret+=tmp;
}
if (!ret) dis[k]=-1;
return ret;
} int dinic(int S,int T)
{
int ret=0,tmp=0;//printf("dinic %d %d\n",S,T);
s=S;t=T;
while (tell()) while (tmp=zeng(s,inf)) ret+=tmp;
return ret;
} void build()
{
en=0;memset(h,-1,sizeof h);memset(a,0,sizeof a);
memset(du,0,sizeof du);
memset(ban,0,sizeof ban);Sum=0;
tot=0;
F(i,1,n) F(j,1,m)
{
if (up[i][j]<down[i][j]) {ans=0;return;}
du[i]-=down[i][j];
du[j+n]+=down[i][j];
up[i][j]-=down[i][j];
a[i][j]+=down[i][j];
add(i,j+n,up[i][j]);
}
F(i,1,n) add(S,i,row[i]);
F(j,n+1,n+m) add(j,T,clu[j-n]);
add(T,S,inf);
F(i,1,n+m)
{
if (du[i]>0) add(SS,i,du[i]),Sum+=du[i];
else if (du[i]<0) add(i,TT,-du[i]);
}
if (dinic(SS,TT)!=Sum) {ans=0;return;}
else
{
ban[en-1]=1;ban[en-2]=1;
for (int i=h[SS];i>=0;i=ne[i]) ban[i]=ban[i^1]=1;
for (int i=h[TT];i>=0;i=ne[i]) ban[i]=ban[i^1]=1;
if (dinic(S,T)!=SSum) {ans=0;return;}
F(i,1,n)
{
for (int j=h[i];j>=0;j=ne[j])
a[i][to[j]-n]+=fl[j^1];
}
ans=1; return;
}
} int main()
{
scanf("%d",&tt);
while (tt--)
{
memset(down,0,sizeof down);
memset(up,0x3f,sizeof up);
scanf("%d%d",&n,&m);SSum=SSSum=0;
F(i,1,n) scanf("%d",&row[i]),SSum+=row[i];
F(i,1,m) scanf("%d",&clu[i]),SSSum+=clu[i];
scanf("%d",&ttt);
F(i,1,ttt)
{
int x,y,z;char s[11];
scanf("%d%d%s%d",&x,&y,s,&z);
switch(s[0])
{
case '>':
if (!x) F(i,1,n)
{
if (!y) F(j,1,m)
down[i][j]=max(down[i][j],z+1);
else
down[i][y]=max(down[i][y],z+1);
}
else
{
if (!y) F(j,1,m)
down[x][j]=max(down[x][j],z+1);
else
down[x][y]=max(down[x][y],z+1);
}
break;
case '=':
if (!x) F(i,1,n)
{
if (!y) F(j,1,m)
{
up[i][j]=min(up[i][j],z);
down[i][j]=max(down[i][j],z);
}
else
{
up[i][y]=min(up[i][y],z);
down[i][y]=max(down[i][y],z);
}
}
else
{
if (!y) F(j,1,m)
{
up[x][j]=min(up[x][j],z);
down[x][j]=max(down[x][j],z);
}
else
{
up[x][y]=min(up[x][y],z);
down[x][y]=max(down[x][y],z);
}
}
break;
case '<':
if (!x) F(i,1,n)
{
if (!y) F(j,1,m)
up[i][j]=min(up[i][j],z-1);
else
up[i][y]=min(up[i][y],z-1);
}
else
{
if (!y) F(j,1,m)
up[x][j]=min(up[x][j],z-1);
else
up[x][y]=min(up[x][y],z-1);
}
break;
}
}
build();
if ((!ans)||(SSum!=SSSum)) printf("IMPOSSIBLE\n");
else
{
F(i,1,n) F(j,1,m)
printf("%d%c",a[i][j],j==m?'\n':' ');
}
if (tt!=0)
printf("\n");
}
}