题目链接:https://vjudge.net/problem/Gym-101611G
解题思路;
解法一;
判断列上横值相加是否为0和横上列值相加是否为0,如果全是则有解,否则无解,
如果列上横值相加等于0,那么就说明可以把这一列的所有横值都变为0.
假设一列的横值为x1,x2,x3....那么在此列的第一个行设置风力为-x1,那么第一个值就变为0,x2则需加上相反数也就是x1,此时x2变为x1+x2,,然后再将第二行风力设为-x1-x2以此类推最后累加是0才能把所有的都变为0.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int mx = 5e2+5;
#define fi first
#define se second
int n,m;
ll r[mx][mx],c[mx][mx];
bool check()
{
for(int j=1;j<=m;j++){
ll ret = 0;
for(int i=1;i<=n;i++){
ret += r[i][j];
}
if(ret!=0) return 0;
}
for(int i=1;i<=n;i++){
ll ret = 0;
for(int j=1;j<=m;j++){
ret += c[i][j];
}
if(ret!=0) return 0;
}
return 1;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%lld",r[i]+j);
scanf("%lld",c[i]+j);
}
}
if(check()) puts("Yes");
else puts("No");
return 0;
}
解法2:
如果我们令f[i][j]表示第i行第j列的格子的风力,那么存在有:
ri[i][j]=f[i][j-1]−f[i][j](c[i][j]同理)
将一个等式变为两个不等式做差分约束系统
保证由任意路径得来的f[i][j]都相同即是有解
#include <cstdio>
typedef long long ll;
const int mx = 5e2 + 10, N = mx * mx, M = N * 8;
int h[N], p[M], v[M], w[M], tot = 0;
int vis[N], id[mx][mx], cnt = 0;
int r[mx][mx], c[mx][mx];
ll f[N];
void add(int a, int b, int c) {
p[++tot] = h[a];
v[tot] = b;
w[tot] = c;
h[a] = tot;
}
bool dfs(int x, ll now) {
if (vis[x]) {
return f[x] == now;
}
vis[x] = 1;
f[x] = now;
for (int i = h[x]; i; i = p[i])
if (!dfs(v[i], now + w[i]))
return 0;
return 1;
}
int main() {
int n, m, i, j;
scanf("%d%d", &n, &m);
for (i = 0; i < n; ++i)
for (j = 0; j < m; ++j) {
scanf("%d%d", &r[i][j], &c[i][j]);
id[i][j] = cnt++;
}
for (i = 0; i < n; ++i)
for (j = 0; j < m; ++j) {
int u = id[i][j];
int v = id[(i - 1 + n) % n][j];
add(u, v, r[i][j]);
// add(v, u, -r[i][j]);
v = id[i][(j - 1 + m) % m];
add(v, u, c[i][j]);
// add(u, v, -c[i][j]);
}
if (!dfs(0, 0)) return puts("No");
return puts("Yes");
}