解析
如果没有元素均要在
[
0
,
1
e
6
]
[0,1e6]
[
0
,
1
e
6
]
的条件,可以很容易的构造出一个合法解。
那么我们就要通过调整得到的解,使所有数都在合法范围内。
注意到,每次给某一行/列依次+1,-1,+1,-1…这样仍然符合要求。
让每一行/列错开,就能变成:
row:
+-+-+
-+-+-
+-+-+
-+-+-
column:
-+-+-
+-+-+
-+-+-
+-+-+
这样每个格子行贡献和列贡献的符号就都是相反的,然后就可以差分约束了。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("OK\n")
using namespace std;
const int N=650;
const int M=50050;
const int mod=1e9+7;
const double eps=1e-9;
inline ll read() {
ll x(0),f(1);char c=getchar();
while(!isdigit(c)) {if(c=='-')f=-1;c=getchar();}
while(isdigit(c)) {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
int n,m;
int a[N][N],b[N][N],c[N],d[N],tot;
ll dis[N];
int o=1e6;
queue<int>q;
bool vis[N];
int tim[N];
struct node{
int to,nxt,w;
}p[N*N*2];
int fi[N],cnt;
inline void addline(int x,int y,int w){
p[++cnt]=(node){y,fi[x],w};fi[x]=cnt;
}
bool spfa(){
memset(dis,0,sizeof(dis));
memset(tim,0,sizeof(tim));
for(int i=1;i<=tot;i++) q.push(i),vis[i]=1;
while(!q.empty()){
int now=q.front();q.pop();
vis[now]=0;
for(int i=fi[now];~i;i=p[i].nxt){
int to=p[i].to;
if(dis[to]<dis[now]+p[i].w){
dis[to]=dis[now]+p[i].w;
tim[to]++;
if(!vis[to]){
vis[to]=1;q.push(to);
}
if(tim[to]>tot) return false;
}
}
}
return true;
}
void work(){
memset(a,0,sizeof(a));tot=0;
memset(fi,-1,sizeof(fi));cnt=-1;
n=read();m=read();
for(int i=1;i<n;i++){
for(int j=1;j<m;j++) b[i][j]=read();
}
for(int i=n-1;i>=1;i--){
for(int j=m-1;j>=1;j--) a[i][j]=b[i][j]-a[i+1][j+1]-a[i+1][j]-a[i][j+1];
}
//for(int i=1;i<=n;i++){
//for(int j=1;j<=m;j++) printf("%d ",a[i][j]);
//puts("");
//}
for(int i=1;i<=n;i++) c[i]=++tot;
for(int j=1;j<=m;j++) d[j]=++tot;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if((i+j)&1){
addline(c[i],d[j],a[i][j]-o);
addline(d[j],c[i],-a[i][j]);
}
else{
addline(c[i],d[j],-a[i][j]);
addline(d[j],c[i],a[i][j]-o);
}
}
}
//for(int i=1;i<=tot;i++)
// for(int j=1;j<=tot;j++) printf("%d -> %d w=%d\n",i,j,e[i][j]);
if(!spfa()){
puts("NO");return;
}
puts("YES");
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
ll add=dis[c[i]]-dis[d[j]];
if((i+j)&1) a[i][j]+=add;
else a[i][j]-=add;
printf("%d ",a[i][j]);
}
puts("");
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
int T=read();
while(T--) work();
return 0;
}
/*
1
3 3
1000000 2000000
0 0
*/
版权声明:本文为BUG_Creater_jie原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。