题目大意:有一个n*m的矩阵,已知每行每列的和,并给出矩阵内元素aij的一些限制,求是否有这样的矩阵
上下界网络流大体分为三种,以下论文详细介绍了这三种问题,并说明了解法
《一种简易的方法求解流量有上下界的网络中网络流问题》 安徽 周源
如果看完了上面的论文,这个题还是很好做的。虚拟一个源点,连到每行代表的点,上下界都为该行的和;虚拟一个汇点,每一列都连到这个点,上下界都为该列的和;每行和每列代表的点相连,上下界为对应元素的限制。显然,如果这个图,能有一个可行流,则原题有解。但是这里有一个问题,这个图是有源汇的,而我们只能判断无源汇的图是否有可行流。解决这个问题也很简单,我们从汇点到源点连一条边,上下界为(0,∞)。至此,问题可解。
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<cctype>
#include<string>
#include<algorithm>
#include<iostream>
#include<ctime>
#include<map>
#include<set>
using namespace std;
#define MP(x,y) make_pair((x),(y))
#define PB(x) push_back(x)
typedef __int64 LL;
//typedef unsigned __int64 ULL;
/* ****************** */
const int INF=100011122;
const double INFF=1e100;
const double eps=1e-8;
const LL mod=9999991;
const int NN=205;
const int MM=2000010;
/* ****************** */
int B[NN][NN],C[NN][NN],M[NN*2];
int s_row[NN],s_col[NN];
int a[NN][NN];
struct G
{
int u,v,cap,next;
}E[NN*NN*2];
int p[NN*2],T;
int tp[NN*2],dd[NN*2],qw[NN*2];
void init(int n,int m)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
B[i][j]=0;
C[i][j]=INF;
}
for(int i=1;i<=n;i++)
s_row[i]=0;
for(int i=1;i<=n;i++)
s_col[i]=0;
for(int i=0;i<=n+m+1;i++)
M[i]=0;
}
void add(int u,int v,int cap)
{
E[T].u=u;
E[T].v=v;
E[T].cap=cap;
E[T].next=p[u];
p[u]=T++;
E[T].u=v;
E[T].v=u;
E[T].cap=0;
E[T].next=p[v];
p[v]=T++;
}
bool find_path(int st,int en,int n)
{
int u,v,i,head,tail;
for(i=0;i<=n;i++)
dd[i]=-1;
qw[head=tail=0]=st;
dd[st]=0;
while(head<=tail)
{
u=qw[head++];
for(i=p[u];i+1;i=E[i].next)
{
v=E[i].v;
if(dd[v]==-1 && E[i].cap>0)
{
dd[v]=dd[u]+1;
qw[++tail]=v;
}
}
}
return (dd[en]!=-1);
}
int dfs_flow(int u,int &en,int f)
{
if(u==en || f==0)
return f;
int temp,flow=0;
for(;tp[u]+1;tp[u]=E[ tp[u] ].next)
{
G &e = E[tp[u]];
if(dd[e.v]==dd[u]+1)
{
temp=dfs_flow(e.v,en,min(f,e.cap));
if(temp>0)
{
f-=temp;
flow+=temp;
e.cap-=temp;
E[tp[u]^1].cap+=temp;
if(f==0)
break;
}
}
}
return flow;
}
int dinic(int st,int en,int n)
{
int i,ans=0;
while( find_path(st,en,n) )
{
for(i=0;i<=n;i++)
tp[i]=p[i];
ans+=dfs_flow(st,en,INF);
}
return ans;
}
void FF(int n,int m)
{
int i,j;
for(i=1;i<T;i+=2)
{
if(n<E[i].u && E[i].v<=n+m && 1<=E[i].v && E[i].v<=n)
{
a[E[i].v][E[i].u-n]=E[i].cap;
}
}
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
printf("%d%c",a[i][j]+B[i][j],j==m?'\n':' ');
}
int main()
{
int cas;
int n,m,q,x,y,c,i,j,sum;
int st,en;
bool fg;
char op[5];
scanf("%d",&cas);
while(cas--)
{
scanf("%d%d",&n,&m);
init(n,m);
memset(p,-1,sizeof(p));
T=0;
sum=0;
st=n+m+2;
en=st+1;
fg=true;
for(i=1;i<=n;i++)
{
scanf("%d",&s_row[i]);
M[0]-=s_row[i];
M[i]+=s_row[i];
}
for(i=1;i<=m;i++)
{
scanf("%d",&s_col[i]);
M[n+m+1]+=s_col[i];
M[n+i]-=s_col[i];
}
scanf("%d",&q);
while(q--)
{
scanf("%d%d",&x,&y);
scanf("%s%d",op,&c);
if(x==0)
i=1,x=n;
else
i=x;
if(y==0)
j=1,y=m;
else
j=y;
for(;i<=x;i++)
for(int ii=j;ii<=y;ii++)
{
if(op[0]=='>')
B[i][ii]=max(B[i][ii],c+1);
else if(op[0]=='<')
C[i][ii]=min(C[i][ii],c-1);
else
{
B[i][ii]=max(B[i][ii],c);
C[i][ii]=min(C[i][ii],c);
}
}
}
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
M[i]-=B[i][j];
M[n+j]+=B[i][j];
}
for(i=0;i<=n+m+1;i++)
{
if(M[i]>=0)
{
add(st,i,M[i]);
sum+=M[i];
}
else
add(i,en,-M[i]);
}
add(n+m+1,0,INF);
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
add(i,n+j,C[i][j]-B[i][j]);
if(C[i][j]-B[i][j]<0)
fg=false;
}
if(fg && dinic(st,en,en)==sum)
{
FF(n,m);
}
else
{
puts("IMPOSSIBLE");
}
puts("");
}
return 0;
}